bug fixes, improved input handling and started testing with typing mode

This commit is contained in:
Dennis Eichhorn 2025-01-11 01:26:44 +01:00
parent 2ecb47117b
commit a02963607d
61 changed files with 949 additions and 755 deletions

View File

@ -10,8 +10,8 @@
#ifndef TOS_ANIMATION_H #ifndef TOS_ANIMATION_H
#define TOS_ANIMATION_H #define TOS_ANIMATION_H
#include <math.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
#include "AnimationEaseType.h" #include "AnimationEaseType.h"

View File

@ -165,6 +165,11 @@ void asset_archive_load(AssetArchive* archive, const char* path, BufferMemory* b
file.content = ring_get_memory(ring, file.size); file.content = ring_get_memory(ring, file.size);
file_read(archive->fd, &file, 0, file.size); file_read(archive->fd, &file, 0, file.size);
asset_archive_header_load(&archive->header, file.content, steps); asset_archive_header_load(&archive->header, file.content, steps);
LOG_LEVEL_2(
"Loaded AssetArchive %s with %d assets",
{{LOG_DATA_CHAR_STR, (void *) path}, {LOG_DATA_UINT32, (void *) &archive->header.asset_count}}
);
} }
// @question Do we want to allow a callback function? // @question Do we want to allow a callback function?
@ -294,6 +299,11 @@ Asset* asset_archive_asset_load(const AssetArchive* archive, int32 id, AssetMana
// the main program should still be able to do some work if possible // the main program should still be able to do some work if possible
thrd_ams_set_loaded(asset); thrd_ams_set_loaded(asset);
LOG_LEVEL_2(
"Asset %d loaded from archive %d for AMS %d with %n B compressed and %n B uncompressed",
{{LOG_DATA_UINT64, &id}, {LOG_DATA_UINT32, &element->type}, {LOG_DATA_BYTE, &component_id}, {LOG_DATA_UINT32, &element->length}, {LOG_DATA_UINT32, &element->uncompressed}}
);
// @performance maybe do in worker threads? This just feels very slow // @performance maybe do in worker threads? This just feels very slow
// @bug dependencies might be stored in different archives? // @bug dependencies might be stored in different archives?
for (uint32 i = 0; i < element->dependency_count; ++i) { for (uint32 i = 0; i < element->dependency_count; ++i) {

View File

@ -45,6 +45,8 @@ void ams_create(AssetManagementSystem* ams, BufferMemory* buf, int32 asset_compo
hashmap_create(&ams->hash_map, count, sizeof(HashEntry) + sizeof(Asset), buf); hashmap_create(&ams->hash_map, count, sizeof(HashEntry) + sizeof(Asset), buf);
ams->asset_component_count = asset_component_count; ams->asset_component_count = asset_component_count;
ams->asset_components = (AssetComponent *) buffer_get_memory(buf, asset_component_count * sizeof(AssetComponent), 64, true); ams->asset_components = (AssetComponent *) buffer_get_memory(buf, asset_component_count * sizeof(AssetComponent), 64, true);
LOG_LEVEL_2("Created AMS for %n assets", {{LOG_DATA_INT32, &count}});
} }
inline inline
@ -54,6 +56,8 @@ void ams_component_create(AssetComponent* ac, BufferMemory* buf, int32 chunk_siz
chunk_init(&ac->asset_memory, buf, count, chunk_size, 64); chunk_init(&ac->asset_memory, buf, count, chunk_size, 64);
pthread_mutex_init(&ac->mutex, NULL); pthread_mutex_init(&ac->mutex, NULL);
LOG_LEVEL_2("Created AMS Component for %n assets and %n B = %n B", {{LOG_DATA_INT32, &count}, {LOG_DATA_UINT32, &chunk_size}, {LOG_DATA_UINT64, &ac->asset_memory.size}});
} }
inline inline
@ -69,6 +73,8 @@ void ams_component_create(AssetComponent* ac, byte* buf, int32 chunk_size, int32
ac->asset_memory.free = (uint64 *) (ac->asset_memory.memory + ac->asset_memory.chunk_size * count); ac->asset_memory.free = (uint64 *) (ac->asset_memory.memory + ac->asset_memory.chunk_size * count);
pthread_mutex_init(&ac->mutex, NULL); pthread_mutex_init(&ac->mutex, NULL);
LOG_LEVEL_2("Created AMS Component for %n assets and %n B = %n B", {{LOG_DATA_INT32, &count}, {LOG_DATA_UINT32, &chunk_size}, {LOG_DATA_UINT64, &ac->asset_memory.size}});
} }
inline inline
@ -216,7 +222,7 @@ Asset* thrd_ams_get_reserve_asset_wait(AssetManagementSystem* ams, byte type, co
ac->ram_size += asset->ram_size; ac->ram_size += asset->ram_size;
++ac->asset_count; ++ac->asset_count;
DEBUG_MEMORY_RESERVE((uint64) asset, asset->ram_size, 180); DEBUG_MEMORY_RESERVE((uintptr_t) asset, asset->ram_size, 180);
return asset; return asset;
} }
@ -389,7 +395,7 @@ Asset* ams_reserve_asset(AssetManagementSystem* ams, byte type, const char* name
ac->ram_size += asset->ram_size; ac->ram_size += asset->ram_size;
++ac->asset_count; ++ac->asset_count;
DEBUG_MEMORY_RESERVE((uint64) asset, asset->ram_size, 180); DEBUG_MEMORY_RESERVE((uintptr_t) asset, asset->ram_size, 180);
return asset; return asset;
} }
@ -422,7 +428,7 @@ Asset* thrd_ams_reserve_asset(AssetManagementSystem* ams, byte type, const char*
ac->ram_size += asset.ram_size; ac->ram_size += asset.ram_size;
++ac->asset_count; ++ac->asset_count;
DEBUG_MEMORY_RESERVE((uint64) asset_data, asset.ram_size, 180); DEBUG_MEMORY_RESERVE((uintptr_t) asset_data, asset.ram_size, 180);
ASSERT_SIMPLE(strlen(name) < HASH_MAP_MAX_KEY_LENGTH - 1); ASSERT_SIMPLE(strlen(name) < HASH_MAP_MAX_KEY_LENGTH - 1);
@ -499,7 +505,7 @@ Asset* ams_insert_asset(AssetManagementSystem* ams, Asset* asset_temp, const cha
++ac->asset_count; ++ac->asset_count;
Asset* asset = (Asset *) hashmap_insert(&ams->hash_map, name, (byte *) asset_temp)->value; Asset* asset = (Asset *) hashmap_insert(&ams->hash_map, name, (byte *) asset_temp)->value;
DEBUG_MEMORY_RESERVE((uint64) asset->self, asset->ram_size, 180); DEBUG_MEMORY_RESERVE((uintptr_t) asset->self, asset->ram_size, 180);
return asset; return asset;
} }
@ -530,7 +536,7 @@ Asset* thrd_ams_insert_asset(AssetManagementSystem* ams, Asset* asset_temp, cons
++ac->asset_count; ++ac->asset_count;
Asset* asset = (Asset *) hashmap_insert(&ams->hash_map, name, (byte *) asset_temp)->value; Asset* asset = (Asset *) hashmap_insert(&ams->hash_map, name, (byte *) asset_temp)->value;
DEBUG_MEMORY_RESERVE((uint64) asset->self, asset->ram_size, 180); DEBUG_MEMORY_RESERVE((uintptr_t) asset->self, asset->ram_size, 180);
atomic_set_release(&asset->is_loaded, 1); atomic_set_release(&asset->is_loaded, 1);

View File

@ -13,7 +13,6 @@
#include "Audio.h" #include "Audio.h"
#include "AudioSetting.h" #include "AudioSetting.h"
#include "../utils/Utils.h" #include "../utils/Utils.h"
#include "../utils/MathUtils.h"
#include "../memory/ChunkMemory.h" #include "../memory/ChunkMemory.h"
#include "../math/matrix/MatrixFloat32.h" #include "../math/matrix/MatrixFloat32.h"
#include "../thread/Atomic.h" #include "../thread/Atomic.h"

View File

@ -14,7 +14,6 @@
#include <string.h> #include <string.h>
#include "../../EngineDependencies/curl/include/curl/curl.h" #include "../../EngineDependencies/curl/include/curl/curl.h"
#include "../utils/MathUtils.h"
#define MAX_AUTH_POST_LENGTH 1024 #define MAX_AUTH_POST_LENGTH 1024
#define MAX_AUTH_RESPONSE_LENGTH 1024 #define MAX_AUTH_RESPONSE_LENGTH 1024

View File

@ -29,6 +29,8 @@ void cmd_buffer_create(AppCmdBuffer* cb, BufferMemory* buf, int32 commands_count
{ {
chunk_init(&cb->commands, buf, commands_count, sizeof(Command), 64); chunk_init(&cb->commands, buf, commands_count, sizeof(Command), 64);
pthread_mutex_init(&cb->mutex, NULL); pthread_mutex_init(&cb->mutex, NULL);
LOG_LEVEL_2("Created AppCmdBuffer: %n B", {{LOG_DATA_UINT64, &cb->commands.size}});
} }
// This doesn't load the asset directly but tells (most likely) a worker thread to load an asset // This doesn't load the asset directly but tells (most likely) a worker thread to load an asset

View File

@ -14,7 +14,6 @@
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/BitUtils.h" #include "../utils/BitUtils.h"
#include "../utils/MathUtils.h"
#include "../utils/EndianUtils.h" #include "../utils/EndianUtils.h"
struct HuffmanNode { struct HuffmanNode {

View File

@ -108,7 +108,7 @@ Entity* ecs_insert_entity(EntityComponentSystem* ecs, Entity* entity_temp, int32
memcpy(entity, entity_temp, mem->chunk_size); memcpy(entity, entity_temp, mem->chunk_size);
// @todo log entity stats (count, ram, vram) // @todo log entity stats (count, ram, vram)
//DEBUG_MEMORY_RESERVE((uint64) entity, entity->ram_size, 180); //DEBUG_MEMORY_RESERVE((uintptr_t) entity, entity->ram_size, 180);
return entity; return entity;
} }

View File

@ -2,7 +2,6 @@
#define TOS_ENVIRONMENT_GLOBE_H #define TOS_ENVIRONMENT_GLOBE_H
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
#include <math.h> #include <math.h>
/** /**

View File

@ -363,6 +363,8 @@ void text_calculate_dimensions(
// @todo implement shadow (offset + angle + diffuse) or should this be a shader only thing? if so this would be a problem for us since we are handling text in the same shader as simple shapes // @todo implement shadow (offset + angle + diffuse) or should this be a shader only thing? if so this would be a problem for us since we are handling text in the same shader as simple shapes
// we might want to implement distance field font atlas // we might want to implement distance field font atlas
// @todo We should be able to cut off text at an arbitrary position, not just at a line_height incremental
// we could probably get the MIN of the glyph height and the remaining window height
v2_f32 vertex_text_create( v2_f32 vertex_text_create(
Vertex3DTextureColorIndex* __restrict vertices, uint32* __restrict index, f32 zindex, Vertex3DTextureColorIndex* __restrict vertices, uint32* __restrict index, f32 zindex,
f32 x, f32 y, f32 width, f32 height, int32 align_h, int32 align_v, f32 x, f32 y, f32 width, f32 height, int32 align_h, int32 align_v,
@ -395,11 +397,19 @@ v2_f32 vertex_text_create(
} }
} }
f32 line_height_scaled = font->line_height * scale;
f32 rendered_width = 0;
f32 rendered_height = line_height_scaled;
f32 offset_x = x; f32 offset_x = x;
for (int32 i = 0; i < length; ++i) { for (int32 i = 0; i < length; ++i) {
int32 character = is_ascii ? text[i] : utf8_get_char_at(text, i); int32 character = is_ascii ? text[i] : utf8_get_char_at(text, i);
if (character == '\n') { if (character == '\n') {
y -= font->line_height * scale; rendered_height += line_height_scaled;
rendered_width = OMS_MAX(rendered_width, offset_x - x);
y -= line_height_scaled;
offset_x = x; offset_x = x;
continue; continue;
@ -429,7 +439,7 @@ v2_f32 vertex_text_create(
// This way we can ensure no overflow easily // This way we can ensure no overflow easily
// @todo implement line alignment, currently only total alignment is considered // @todo implement line alignment, currently only total alignment is considered
return {offset_x, y}; return {rendered_width, rendered_height};
} }
// @todo implement shadow (offset + angle + diffuse) or should this be a shader only thing? if so this would be a problem for us since we are handling text in the same shader as simple shapes // @todo implement shadow (offset + angle + diffuse) or should this be a shader only thing? if so this would be a problem for us since we are handling text in the same shader as simple shapes

View File

@ -41,7 +41,7 @@ ID3D12PipelineState* program_make(
HRESULT hr = device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)); HRESULT hr = device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState));
if (FAILED(hr)) { if (FAILED(hr)) {
LOG("Failed to create program", true, true); LOG(true, "Failed to create program");
return NULL; return NULL;
} }

View File

@ -44,7 +44,7 @@ void opengl_debug_callback(GLenum source, GLenum type, GLuint id, GLenum severit
return; return;
} }
LOG(message, true, true); LOG(true, message);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -490,6 +490,7 @@ void gpuapi_error()
{ {
GLenum err; GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) { while ((err = glGetError()) != GL_NO_ERROR) {
LOG_FORMAT(true, "Opengl error: %d", {{LOG_DATA_INT32, (int32 *) &err}});
ASSERT_SIMPLE(err == GL_NO_ERROR); ASSERT_SIMPLE(err == GL_NO_ERROR);
} }
} }

View File

@ -275,7 +275,7 @@ GLuint shader_make(GLenum type, const char* source, RingMemory* ring)
GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar));
glGetShaderInfoLog(shader, length, NULL, info); glGetShaderInfoLog(shader, length, NULL, info);
LOG(info, true, true); LOG(true, info);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -321,7 +321,7 @@ GLuint program_make(
GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar));
glGetProgramInfoLog(program, length, NULL, info); glGetProgramInfoLog(program, length, NULL, info);
LOG(info, true, true); LOG(true, info);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }

View File

@ -58,7 +58,7 @@ VkShaderModule shader_make(VkDevice device, const char* source, int32 source_siz
VkResult result = vkCreateShaderModule(device, &create_info, NULL, &shader_module); VkResult result = vkCreateShaderModule(device, &create_info, NULL, &shader_module);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
LOG("Failed to create shader module", true, true); LOG(true, "Failed to create shader module");
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
return VK_NULL_HANDLE; return VK_NULL_HANDLE;

View File

@ -111,7 +111,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_callback(
if ((severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) if ((severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
|| (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) || (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
) { ) {
LOG(debug_callback_data->pMessage, true, true); LOG(true, debug_callback_data->pMessage);
} }
return VK_FALSE; return VK_FALSE;
@ -158,14 +158,14 @@ void vulkan_instance_create(
if (validation_layer_count if (validation_layer_count
&& (err = vulkan_check_validation_layer_support(validation_layers, validation_layer_count, ring)) && (err = vulkan_check_validation_layer_support(validation_layers, validation_layer_count, ring))
) { ) {
LOG_FORMAT("Vulkan validation_layer missing: %d\n", LOG_DATA_CHAR_STR, (void *) validation_layers[-err - 1], true, true); LOG_FORMAT(true, "Vulkan validation_layer missing: %d", {{LOG_DATA_CHAR_STR, (void *) validation_layers[-err - 1]}});
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
if (extension_count if (extension_count
&& (err = vulkan_check_extension_support(extensions, extension_count, ring)) && (err = vulkan_check_extension_support(extensions, extension_count, ring))
) { ) {
LOG_FORMAT("Vulkan extension missing: %d\n", LOG_DATA_CHAR_STR, (void *) extensions[-err - 1], true, true); LOG_FORMAT(true, "Vulkan extension missing: %d", {{LOG_DATA_CHAR_STR, (void *) extensions[-err - 1]}});
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -195,7 +195,7 @@ void vulkan_instance_create(
VkResult result; VkResult result;
if ((result = vkCreateInstance(&create_info, NULL, instance)) != VK_SUCCESS) { if ((result = vkCreateInstance(&create_info, NULL, instance)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateInstance: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateInstance: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
@ -210,7 +210,7 @@ void vulkan_surface_create(VkInstance instance, VkSurfaceKHR* surface, Window* w
VkResult result; VkResult result;
if ((result = vkCreateWin32SurfaceKHR(instance, &surface_create_info, NULL, surface)) != VK_SUCCESS) { if ((result = vkCreateWin32SurfaceKHR(instance, &surface_create_info, NULL, surface)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateWin32SurfaceKHR: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateWin32SurfaceKHR: %d", LOG_DATA_INT32, (int32 *) &result);
return; return;
} }
#elif __linux__ #elif __linux__
@ -345,7 +345,7 @@ void gpuapi_pick_physical_device(
} }
} }
LOG("Vulkan failed to find physical device\n", true, true); LOG(true, "Vulkan failed to find physical device");
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -392,7 +392,7 @@ void gpuapi_create_logical_device(
VkResult result; VkResult result;
if ((result = vkCreateDevice(physical_device, &create_info, NULL, device)) != VK_SUCCESS) { if ((result = vkCreateDevice(physical_device, &create_info, NULL, device)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateDevice: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateDevice: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -480,7 +480,7 @@ void vulkan_swap_chain_create(
VkResult result; VkResult result;
if ((result = vkCreateSwapchainKHR(device, &create_info, NULL, swapchain)) != VK_SUCCESS) { if ((result = vkCreateSwapchainKHR(device, &create_info, NULL, swapchain)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateSwapchainKHR: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateSwapchainKHR: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -521,7 +521,7 @@ void vulkan_image_views_create(
create_info.subresourceRange.layerCount = 1; create_info.subresourceRange.layerCount = 1;
if ((result = vkCreateImageView(device, &create_info, NULL, &swapchain_image_views[i])) != VK_SUCCESS) { if ((result = vkCreateImageView(device, &create_info, NULL, &swapchain_image_views[i])) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateImageView: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateImageView: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
@ -568,7 +568,7 @@ void create_render_pass(
VkResult result; VkResult result;
if ((result = vkCreateRenderPass(device, &renderPassInfo, NULL, render_pass)) != VK_SUCCESS) { if ((result = vkCreateRenderPass(device, &renderPassInfo, NULL, render_pass)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateRenderPass: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateRenderPass: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
@ -665,7 +665,7 @@ void vulkan_pipeline_create(
VkResult result; VkResult result;
if ((result = vkCreatePipelineLayout(device, &pipelineLayoutInfo, NULL, pipeline_layout)) != VK_SUCCESS) { if ((result = vkCreatePipelineLayout(device, &pipelineLayoutInfo, NULL, pipeline_layout)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreatePipelineLayout: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreatePipelineLayout: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -686,7 +686,7 @@ void vulkan_pipeline_create(
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if ((result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, pipeline)) != VK_SUCCESS) { if ((result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, pipeline)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateGraphicsPipelines: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateGraphicsPipelines: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -717,7 +717,7 @@ void vulkan_framebuffer_create(
framebufferInfo.layers = 1; framebufferInfo.layers = 1;
if ((result = vkCreateFramebuffer(device, &framebufferInfo, NULL, &swapchain_framebuffers[i])) != VK_SUCCESS) { if ((result = vkCreateFramebuffer(device, &framebufferInfo, NULL, &swapchain_framebuffers[i])) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateFramebuffer: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateFramebuffer: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
@ -736,7 +736,7 @@ void vulkan_command_pool_create(
VkResult result; VkResult result;
if ((result = vkCreateCommandPool(device, &poolInfo, NULL, command_pool)) != VK_SUCCESS) { if ((result = vkCreateCommandPool(device, &poolInfo, NULL, command_pool)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkCreateCommandPool: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkCreateCommandPool: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
@ -751,7 +751,7 @@ void vulkan_command_buffer_create(VkDevice device, VkCommandBuffer* command_buff
VkResult result; VkResult result;
if ((result = vkAllocateCommandBuffers(device, &allocInfo, command_buffer)) != VK_SUCCESS) { if ((result = vkAllocateCommandBuffers(device, &allocInfo, command_buffer)) != VK_SUCCESS) {
LOG_FORMAT("Vulkan vkAllocateCommandBuffers: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vkAllocateCommandBuffers: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
@ -770,7 +770,7 @@ void vulkan_sync_objects_create(VkDevice device, VkSemaphore* image_available_se
|| (result = vkCreateSemaphore(device, &semaphoreInfo, NULL, render_finished_semaphore)) != VK_SUCCESS || (result = vkCreateSemaphore(device, &semaphoreInfo, NULL, render_finished_semaphore)) != VK_SUCCESS
|| (result = vkCreateFence(device, &fenceInfo, NULL, in_flight_fence)) != VK_SUCCESS || (result = vkCreateFence(device, &fenceInfo, NULL, in_flight_fence)) != VK_SUCCESS
) { ) {
LOG_FORMAT("Vulkan vulkan_sync_objects_create: %d\n", LOG_DATA_INT32, (int32 *) &result, true, true); LOG_FORMAT(true, "Vulkan vulkan_sync_objects_create: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }

View File

@ -15,7 +15,6 @@
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/Utils.h" #include "../utils/Utils.h"
#include "../utils/EndianUtils.h" #include "../utils/EndianUtils.h"
#include "../utils/MathUtils.h"
#include "Image.h" #include "Image.h"
// See: https://en.wikipedia.org/wiki/BMP_file_format // See: https://en.wikipedia.org/wiki/BMP_file_format

View File

@ -15,22 +15,22 @@
// @todo basically all the dark colors could be made darker -> space out some of the very bright colors a little bit more (see 3rd - 5th column) // @todo basically all the dark colors could be made darker -> space out some of the very bright colors a little bit more (see 3rd - 5th column)
const uint32 default_colors_256[256] = { const uint32 default_colors_256[256] = {
0xFFFFFF00, 0xFFFFFFFF, 0xF1EEEDFF, 0xDCDEDEFF, 0xBFC1BFFF, 0xAEB0ADFF, 0x9E9D9EFF, 0x8E8F94FF, 0x717373FF, 0x5E5F61FF, 0x4D4D4CFF, 0x3F403AFF, 0x332C2AFF, 0x241E22FF, 0x0C1210FF, 0x000000FF, 0xFFFFFF00, 0xFFFFFFFF, 0xE9E9E9FF, 0xD9D9D9FF, 0xC9C9C9FF, 0xB9B9B9FF, 0xA9A9A9FF, 0x999999FF, 0x898989FF, 0x797979FF, 0x696969FF, 0x595959FF, 0x494949FF, 0x393939FF, 0x1F1F1FFF, 0x000000FF,
0xF6D3CFFF, 0xFABABCFF, 0xFBA699FF, 0xF19580FF, 0xFB837AFF, 0xFC615AFF, 0xFF4E4BFF, 0xFF4040FF, 0xF72128FF, 0xF60303FF, 0xE40000FF, 0xC70002FF, 0x900009FF, 0x630604FF, 0x4f0107FF, 0x2d0205FF, 0xF6D3CFFF, 0xF8C2BDFF, 0xFB9E91FF, 0xFC8B7EFF, 0xFC796CFF, 0xFD675BFF, 0xFF554BFF, 0xFF4340FF, 0xF82D2EFF, 0xF6171BFF, 0xE60412FF, 0xCC0004FF, 0xA70004FF, 0x7A0306FF, 0x4f0107FF, 0x330004FF,
0xFDDDCEFF, 0xFCC5ACFF, 0xFFB9A4FF, 0xF6A378FF, 0xF49A80FF, 0xFF7D4FFF, 0xF8742CFF, 0xFE5A22FF, 0xF44A0BFF, 0xDA3A06FF, 0xC03500FF, 0x853004FF, 0x912600FF, 0x672300FF, 0x471608FF, 0x2b0d05FF, 0xFDDDCEFF, 0xFCCFB6FF, 0xFDB69EFF, 0xF5A78CFF, 0xF69B7EFF, 0xFF8A65FF, 0xFF7A50FF, 0xFB683AFF, 0xF95523FF, 0xF34413FF, 0xD8390AFF, 0xB22F07FF, 0x8F2905FF, 0x742406FF, 0x57200AFF, 0x2b0d05FF,
0xFCEBCFFF, 0xFCD8AAFF, 0xFFCD98FF, 0xFCC27FFF, 0xF3B267FF, 0xFDA660FF, 0xFD942DFF, 0xFF8001FF, 0xDF6E00FF, 0xCC6B00FF, 0xA85D00FF, 0xA55300FF, 0x734700FF, 0x612D08FF, 0x562600FF, 0x351700FF, 0xFCEBCFFF, 0xFCDAB2FF, 0xFCCB96FF, 0xFBBE7CFF, 0xF3B067FF, 0xFCA45FFF, 0xFB913EFF, 0xFF7F1CFF, 0xE76E09FF, 0xD06B00FF, 0xB05F00FF, 0x9C5300FF, 0x824A00FF, 0x6E3B06FF, 0x5A2E05FF, 0x351700FF,
0xFFF6C9FF, 0xFFECA8FF, 0xFDE884FF, 0xFADC6DFF, 0xF8DE6FFF, 0xFFCF43FF, 0xFFBD00FF, 0xEBB800FF, 0xC1A800FF, 0xBC8F09FF, 0x9B7A00FF, 0x8E6C08FF, 0x795F01FF, 0x5C4A00FF, 0x523B00FF, 0x392900FF, 0xFFF6C9FF, 0xFFEDB1FF, 0xFFE593FF, 0xFDDC74FF, 0xF9D36AFF, 0xFFC94FFF, 0xFFBD1EFF, 0xF4B600FF, 0xD2A200FF, 0xB78E04FF, 0x9D7D00FF, 0x8C6F07FF, 0x776300FF, 0x614F00FF, 0x503D00FF, 0x392900FF,
0xFFFFCDFF, 0xFDFEAFFF, 0xFCFBA1FF, 0xFDFF69FF, 0xF9FF2AFF, 0xFFFE04FF, 0xEFEE00FF, 0xE0DE00FF, 0xBDBF13FF, 0xB4AF00FF, 0x9F9900FF, 0x909002FF, 0x717300FF, 0x505400FF, 0x4A4F00FF, 0x343700FF, 0xFFFFCDFF, 0xFEFDBCFF, 0xFCF9A3FF, 0xFBF583FF, 0xFAF065FF, 0xFFEA2BFF, 0xFEEB04FF, 0xE9DC00FF, 0xD7CC00FF, 0xC4BA00FF, 0xADA500FF, 0x9A9200FF, 0x7C7700FF, 0x605B00FF, 0x4F4C00FF, 0x343700FF,
0xE4FFBDFF, 0xDFFEB9FF, 0xD1FF8FFF, 0xCAFC84FF, 0xC0F96BFF, 0xBAF353FF, 0x98FB00FF, 0x9AEE0FFF, 0x78CE00FF, 0x74C100FF, 0x61A401FF, 0x578A03FF, 0x4F7E02FF, 0x3C6200FF, 0x2E4F00FF, 0x203700FF, 0xE4FFBDFF, 0xDBFDBCFF, 0xCEF9A3FF, 0xC4F48EFF, 0xBAEE76FF, 0xB1E760FF, 0x9FEF29FF, 0x97E313FF, 0x7FC900FF, 0x78BB00FF, 0x67A201FF, 0x5C8E02FF, 0x527F01FF, 0x426600FF, 0x334F00FF, 0x203700FF,
0xE1F8D8FF, 0xBBFEADFF, 0xA2F592FF, 0xA1F79AFF, 0x81FF7AFF, 0x5DFF59FF, 0x48FF58FF, 0x00F600FF, 0x12D31FFF, 0x0ACB04FF, 0x10A40AFF, 0x089811FF, 0x06780EFF, 0x05640FFF, 0x005200FF, 0x003100FF, 0xE1F8D8FF, 0xC7F8C2FF, 0xADF5ABFF, 0x9EEC97FF, 0x85E47FFF, 0x66DF66FF, 0x4EDB5FFF, 0x23D138FF, 0x12C72CFF, 0x0EB522FF, 0x109B17FF, 0x0A8913FF, 0x077311FF, 0x066011FF, 0x004F06FF, 0x003100FF,
0xD5FFF8FF, 0xBCFFEAFF, 0xA7FED3FF, 0x99F2C4FF, 0x6CFFB5FF, 0x53F29EFF, 0x4CFEA1FF, 0x0AF779FF, 0x0CD56AFF, 0x0BC868FF, 0x01AA50FF, 0x07A557FF, 0x008642FF, 0x075A30FF, 0x00562CFF, 0x00331aFF, 0xD5FFF8FF, 0xC5FDF4FF, 0xA8F7E5FF, 0x99F0D7FF, 0x7BF1C6FF, 0x60E6B1FF, 0x53E0A0FF, 0x1CE76FFF, 0x0DD763FF, 0x0AD056FF, 0x02B548FF, 0x04A94DFF, 0x009A40FF, 0x088133FF, 0x005A2BFF, 0x00331AFF,
0xD9FDFEFF, 0xB3FCFFFF, 0xACFFFFFF, 0x90FFFFFF, 0x76FEFFFF, 0x5FFAFDFF, 0x08FEFEFF, 0x22F3F2FF, 0x06C9C2FF, 0x08B2C4FF, 0x049FA4FF, 0x078C97FF, 0x008286FF, 0x025D5DFF, 0x005056FF, 0x003135FF, 0xD9FDFEFF, 0xB5FBFEFF, 0xA8FFFFFF, 0x92FFFFFF, 0x7AFDFFFF, 0x66F9FDFF, 0x0FF8FEFF, 0x1CE7F5FF, 0x06C5C9FF, 0x0BA2B2FF, 0x04A39EFF, 0x079A8EFF, 0x008B7DFF, 0x027A7AFF, 0x004D4FFF, 0x003135FF,
0xE2F5FFFF, 0xB4EBFFFF, 0xA3DAFFFF, 0x89CCF8FF, 0x79D1FFFF, 0x61C3F7FF, 0x59C5F3FF, 0x3FB9F6FF, 0x05A4FAFF, 0x0592F0FF, 0x0677B8FF, 0x00649AFF, 0x065A77FF, 0x004974FF, 0x003154FF, 0x00243eFF, 0xE2F5FFFF, 0xB4EBFFFF, 0xA3DAFFFF, 0x89CCF8FF, 0x79D1FFFF, 0x61C3F7FF, 0x59C5F3FF, 0x3FB9F6FF, 0x05A4FAFF, 0x0592F0FF, 0x0677B8FF, 0x00649AFF, 0x065A77FF, 0x004974FF, 0x003154FF, 0x00243eFF,
0xD1DDFFFF, 0xB5D0EFFF, 0xA7BFF6FF, 0x90B6F4FF, 0x85AAF7FF, 0x67AAFFFF, 0x5386FFFF, 0x437AFFFF, 0x3A6AFFFF, 0x044EFCFF, 0x034EF7FF, 0x0A37BFFF, 0x09268BFF, 0x062871FF, 0x001D4CFF, 0x001435FF, 0xD1DDFFFF, 0xB5D0EFFF, 0xA7BFF6FF, 0x90B6F4FF, 0x85AAF7FF, 0x67AAFFFF, 0x5386FFFF, 0x437AFFFF, 0x3A6AFFFF, 0x044EFCFF, 0x034EF7FF, 0x0A37BFFF, 0x09268BFF, 0x062871FF, 0x001D4CFF, 0x001435FF,
0xC7C3FFFF, 0xC7C6FEFF, 0x9D9CFFFF, 0x9194F6FF, 0x7E81FEFF, 0x776FF7FF, 0x595AFFFF, 0x4852FFFF, 0x2D2EFFFF, 0x2020F8FF, 0x0400E1FF, 0x0000DDFF, 0x010097FF, 0x000086FF, 0x03005DFF, 0x020035FF, 0xC7C3FFFF, 0xC7C6FEFF, 0x9D9CFFFF, 0x9194F6FF, 0x7E81FEFF, 0x776FF7FF, 0x595AFFFF, 0x4852FFFF, 0x2D2EFFFF, 0x2020F8FF, 0x0400E1FF, 0x0000DDFF, 0x010097FF, 0x000086FF, 0x03005DFF, 0x020035FF,
0xE1D4FFFF, 0xD8ACFFFF, 0xCD9BFFFF, 0xC88DFAFF, 0xBD8AF9FF, 0xB160FFFF, 0xAA52FEFF, 0x9841FDFF, 0x8726FFFF, 0x8700F5FF, 0x7200F4FF, 0x5C00B7FF, 0x460489FF, 0x350077FF, 0x28004FFF, 0x1c0037FF, 0xE1D4FFFF, 0xD8ACFFFF, 0xCD9BFFFF, 0xC88DFAFF, 0xBD8AF9FF, 0xB160FFFF, 0xAA52FEFF, 0x9841FDFF, 0x8726FFFF, 0x8700F5FF, 0x7200F4FF, 0x5C00B7FF, 0x460489FF, 0x350077FF, 0x28004FFF, 0x1c0037FF,
0xFFC7FFFF, 0xFFB2FFFF, 0xFF9AFFFF, 0xF181F1FF, 0xFB6FFDFF, 0xF850FBFF, 0xFB46FFFF, 0xF91FFFFF, 0xF900FFFF, 0xDD00E6FF, 0xBF00C7FF, 0x9B0199FF, 0xB70090FF, 0x670362FF, 0x4F0153FF, 0x330035FF, 0xFFC7FFFF, 0xFFB8FFFF, 0xFFAAFFFF, 0xF194F7FF, 0xF681F5FF, 0xF77CF1FF, 0xF76DFFFF, 0xF956FFFF, 0xF82FFFFF, 0xEA00E6FF, 0xD200CBFF, 0xB500B3FF, 0xA6009CFF, 0x8A0084FF, 0x6F005EFF, 0x330035FF,
0xFDD2E6FF, 0xF9B5DAFF, 0xF7A4D4FF, 0xF198CBFF, 0xF682BDFF, 0xFF5FAEFF, 0xFF4CA9FF, 0xFF3CA4FF, 0xFF1A94FF, 0xF90979FF, 0xE80071FF, 0xC40061FF, 0x96004AFF, 0x670132FF, 0x4F0024FF, 0x310016FF 0xFDD2E6FF, 0xF9B5DAFF, 0xF7A4D4FF, 0xF198CBFF, 0xF682BDFF, 0xFF5FAEFF, 0xFF4CA9FF, 0xFF3CA4FF, 0xFF1A94FF, 0xF90979FF, 0xE80071FF, 0xC40061FF, 0x96004AFF, 0x670132FF, 0x4F0024FF, 0x310016FF,
}; };
// @todo Implement (extends the default_colors_256 -> both together form 1024 colors) // @todo Implement (extends the default_colors_256 -> both together form 1024 colors)

View File

@ -28,7 +28,7 @@
// How many concurrent primary key/button presses can be handled? // How many concurrent primary key/button presses can be handled?
#define MAX_KEY_PRESSES 5 #define MAX_KEY_PRESSES 5
#define MAX_KEY_STATES (2 * MAX_KEY_PRESSES) #define MAX_KEY_PRESS_TYPES (2 * MAX_KEY_PRESSES)
// How many keys/buttons do we support for the devices // How many keys/buttons do we support for the devices
#define MAX_KEYBOARD_KEYS 255 #define MAX_KEYBOARD_KEYS 255
@ -36,10 +36,6 @@
#define MIN_INPUT_DEVICES 2 #define MIN_INPUT_DEVICES 2
// How often can a key be assigned to a different hotkey
#define MAX_KEY_TO_HOTKEY 5
#define MEX_KEY_LENGTH ((MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS + MAX_CONTROLLER_KEYS) * MAX_KEY_TO_HOTKEY)
// How many buttons together are allowed to form a hotkey // How many buttons together are allowed to form a hotkey
#define MAX_HOTKEY_COMBINATION 3 #define MAX_HOTKEY_COMBINATION 3
@ -63,6 +59,7 @@ enum InputType {
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#include <dinput.h> #include <dinput.h>
#include "../platform/win32/UtilsWin32.h"
#endif #endif
typedef void (*InputCallback)(void* data); typedef void (*InputCallback)(void* data);
@ -70,43 +67,49 @@ typedef void (*InputCallback)(void* data);
// @todo I'm not sure if I like the general input handling // @todo I'm not sure if I like the general input handling
// Having separate keyboard_down and mouse_down etc. is a little bit weird in the functions below // Having separate keyboard_down and mouse_down etc. is a little bit weird in the functions below
struct InputMapping { enum KeyPressType : byte {
// A key/button can be bound to up to 5 different hotkeys KEY_PRESS_TYPE_NONE,
// This is used to check if a key/button has a hotkey association KEY_PRESS_TYPE_PRESSED,
uint8 keys[MEX_KEY_LENGTH]; KEY_PRESS_TYPE_HELD,
KEY_PRESS_TYPE_RELEASED,
// A hotkey can be bound to a combination of up to 3 key/button presses };
uint8 hotkey_count;
struct Hotkey {
// negative hotkeys mean any of them needs to be matched, positive hotkeys means all of them need to be matched // negative hotkeys mean any of them needs to be matched, positive hotkeys means all of them need to be matched
// mixing positive and negative keys for one hotkey is not possible // mixing positive and negative keys for one hotkey is not possible
// index = hotkey, value = key id // index = hotkey, value = key id
int16* hotkeys; int16 scan_codes[MAX_HOTKEY_COMBINATION];
InputCallback* callbacks; KeyPressType key_state;
InputCallback callback;
}; };
enum KeyState { struct InputMapping {
KEY_STATE_PRESSED, // A hotkey can be bound to a combination of up to 3 key/button presses
KEY_STATE_HELD, // The indices represent the hotkey id
KEY_STATE_RELEASED, uint8 hotkey_count;
Hotkey* hotkeys;
}; };
struct InputKey { struct InputKey {
// Includes flag for mouse, keyboard, controller // Includes flag for mouse, keyboard, controller
uint16 key_id; uint16 scan_code;
uint16 key_state; uint16 virtual_code;
int16 value; // e.g. stick/trigger keys have additional values KeyPressType key_state;
uint64 time; // when was this action performed (useful to decide if key state is held vs pressed) uint64 time; // when was this action performed (useful to decide if key state is held vs pressed)
bool is_processed;
int16 value; // e.g. stick/trigger keys have additional values
}; };
// @question Maybe we should also add a third key_down array for controllers and some special controller functions here to just handle everything in one struct // @question Maybe we should also add a third key_down array for controllers and some special controller functions here to just handle everything in one struct
// Or think about completely splitting all states (mouse, keyboard, other) // Or think about completely splitting all states (mouse, keyboard, other)
struct InputState { struct InputState {
// State of the hotkeys, resulting from the device input // Active hotkeys
uint8 state_hotkeys[MAX_KEY_PRESSES]; uint16 active_hotkeys[MAX_KEY_PRESSES];
InputKey state_keys[MAX_KEY_STATES]; // Active keys
InputKey active_keys[MAX_KEY_PRESS_TYPES];
// @question Couldn't we make the values below 16 bit?
int32 dx; int32 dx;
int32 dy; int32 dy;
@ -128,6 +131,13 @@ struct InputState {
uint32 y3; uint32 y3;
}; };
enum GeneralInputState : byte {
INPUT_STATE_GENERAL_BUTTON_CHANGE = 1 << 0,
INPUT_STATE_GENERAL_MOUSE_CHANGE = 1 << 1,
INPUT_STATE_GENERAL_MOUSE_MOVEMENT = 1 << 2,
INPUT_STATE_GENERAL_TYPING_MODE = 1 << 3,
};
struct Input { struct Input {
// Device // Device
InputConnectionType connection_type; InputConnectionType connection_type;
@ -145,17 +155,15 @@ struct Input {
#endif #endif
byte controller_type; byte controller_type;
bool state_change_button; byte general_states;
bool state_change_mouse;
// Do we want to capture mouse events = true,
// or do we want to poll the position whenever needed = false
bool mouse_movement;
InputState state; InputState state;
uint64 time_last_input_check; uint64 time_last_input_check;
// @todo this should probably be somewhere else
// @todo don't we need multiple deadzones? triggers, sticks
uint32 deadzone = 10; uint32 deadzone = 10;
uint32 characters[10];
// This data is passed to the hotkey callback // This data is passed to the hotkey callback
void* callback_data; void* callback_data;
@ -172,247 +180,202 @@ void input_init(Input* input, uint8 size, void* callback_data, BufferMemory* buf
// Init mapping1 // Init mapping1
input->input_mapping1.hotkey_count = size; input->input_mapping1.hotkey_count = size;
input->input_mapping1.hotkeys = (Hotkey *) buffer_get_memory(
input->input_mapping1.hotkeys = (int16 *) buffer_get_memory(
buf, buf,
input->input_mapping1.hotkey_count * MAX_HOTKEY_COMBINATION * sizeof(int16) input->input_mapping1.hotkey_count * sizeof(Hotkey),
); 4, true
input->input_mapping1.callbacks = (InputCallback *) buffer_get_memory(
buf,
input->input_mapping1.hotkey_count * sizeof(InputCallback),
0, true
); );
// Init mapping2 // Init mapping2
input->input_mapping2.hotkey_count = size; input->input_mapping2.hotkey_count = size;
input->input_mapping2.hotkeys = (Hotkey *) buffer_get_memory(
input->input_mapping2.hotkeys = (int16 *) buffer_get_memory(
buf, buf,
input->input_mapping2.hotkey_count * MAX_HOTKEY_COMBINATION * sizeof(int16) input->input_mapping2.hotkey_count * sizeof(Hotkey),
); 4, true
input->input_mapping2.callbacks = (InputCallback *) buffer_get_memory(
buf,
input->input_mapping2.hotkey_count * sizeof(InputCallback),
0, true
); );
} }
inline inline
void input_clean_state(InputKey* state_keys) void input_clean_state(InputKey* active_keys, KeyPressType press_status = KEY_PRESS_TYPE_RELEASED)
{ {
for (int32 i = 0; i < MAX_KEY_STATES; ++i) { if (press_status) {
if (state_keys[i].key_state == KEY_STATE_RELEASED) { for (int32 i = 0; i < MAX_KEY_PRESS_TYPES; ++i) {
state_keys[i].key_id = 0; if (active_keys[i].key_state == press_status) {
memset(&active_keys[i], 0, sizeof(InputKey));
} }
} }
} else {
memset(active_keys, 0, MAX_KEY_PRESS_TYPES * sizeof(InputKey));
}
} }
inline inline
bool input_action_exists(const InputKey* state_keys, int16 key) bool input_action_exists(const InputKey* active_keys, int16 key, KeyPressType press_type = KEY_PRESS_TYPE_PRESSED)
{ {
return state_keys[0].key_id == key return (active_keys[0].scan_code == key && active_keys[0].key_state == press_type)
|| state_keys[1].key_id == key || (active_keys[1].scan_code == key && active_keys[1].key_state == press_type)
|| state_keys[2].key_id == key || (active_keys[2].scan_code == key && active_keys[2].key_state == press_type)
|| state_keys[3].key_id == key || (active_keys[3].scan_code == key && active_keys[3].key_state == press_type)
|| state_keys[4].key_id == key || (active_keys[4].scan_code == key && active_keys[4].key_state == press_type)
|| state_keys[4].key_id == key || (active_keys[4].scan_code == key && active_keys[4].key_state == press_type)
|| state_keys[5].key_id == key || (active_keys[5].scan_code == key && active_keys[5].key_state == press_type)
|| state_keys[6].key_id == key || (active_keys[6].scan_code == key && active_keys[6].key_state == press_type)
|| state_keys[7].key_id == key || (active_keys[7].scan_code == key && active_keys[7].key_state == press_type)
|| state_keys[8].key_id == key || (active_keys[8].scan_code == key && active_keys[8].key_state == press_type)
|| state_keys[9].key_id == key; || (active_keys[9].scan_code == key && active_keys[9].key_state == press_type);
} }
inline inline
bool input_is_down(const InputKey* state_keys, int16 key) bool input_is_down(const InputKey* active_keys, int16 key)
{ {
return (state_keys[0].key_id == key && state_keys[0].key_state != KEY_STATE_RELEASED) return (active_keys[0].scan_code == key && active_keys[0].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[1].key_id == key && state_keys[1].key_state != KEY_STATE_RELEASED) || (active_keys[1].scan_code == key && active_keys[1].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[2].key_id == key && state_keys[2].key_state != KEY_STATE_RELEASED) || (active_keys[2].scan_code == key && active_keys[2].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[3].key_id == key && state_keys[3].key_state != KEY_STATE_RELEASED) || (active_keys[3].scan_code == key && active_keys[3].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[4].key_id == key && state_keys[4].key_state != KEY_STATE_RELEASED) || (active_keys[4].scan_code == key && active_keys[4].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[5].key_id == key && state_keys[5].key_state != KEY_STATE_RELEASED) || (active_keys[5].scan_code == key && active_keys[5].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[6].key_id == key && state_keys[6].key_state != KEY_STATE_RELEASED) || (active_keys[6].scan_code == key && active_keys[6].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[7].key_id == key && state_keys[7].key_state != KEY_STATE_RELEASED) || (active_keys[7].scan_code == key && active_keys[7].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[8].key_id == key && state_keys[8].key_state != KEY_STATE_RELEASED) || (active_keys[8].scan_code == key && active_keys[8].key_state != KEY_PRESS_TYPE_RELEASED)
|| (state_keys[9].key_id == key && state_keys[9].key_state != KEY_STATE_RELEASED); || (active_keys[9].scan_code == key && active_keys[9].key_state != KEY_PRESS_TYPE_RELEASED);
} }
inline inline
bool input_is_pressed(const InputKey* state_keys, int16 key) bool input_is_pressed(const InputKey* active_keys, int16 key)
{ {
return (state_keys[0].key_id == key && state_keys[0].key_state == KEY_STATE_PRESSED) return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_PRESSED) || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_PRESSED) || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_PRESSED) || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_PRESSED) || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_PRESSED) || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_PRESSED) || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_PRESSED) || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_PRESSED) || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_PRESSED)
|| (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_PRESSED); || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_PRESSED);
} }
inline inline
bool input_is_held(const InputKey* state_keys, int16 key) bool input_is_held(const InputKey* active_keys, int16 key)
{ {
return (state_keys[0].key_id == key && state_keys[0].key_state == KEY_STATE_HELD) return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_HELD) || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_HELD) || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_HELD) || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_HELD) || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_HELD) || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_HELD) || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_HELD) || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_HELD) || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_HELD) || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_HELD)
|| (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_HELD); || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_HELD);
} }
inline inline
bool input_is_released(const InputKey* state_keys, int16 key) bool input_is_released(const InputKey* active_keys, int16 key)
{ {
return (state_keys[0].key_id == key && state_keys[0].key_state == KEY_STATE_RELEASED) return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_RELEASED) || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_RELEASED) || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_RELEASED) || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_RELEASED) || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_RELEASED) || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_RELEASED) || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_RELEASED) || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_RELEASED); || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_RELEASED);
} }
inline inline
bool input_was_down(const InputKey* state_keys, int16 key) bool input_was_down(const InputKey* active_keys, int16 key)
{ {
return (state_keys[0].key_id == key && state_keys[0].key_state == KEY_STATE_RELEASED) return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_RELEASED) || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_RELEASED) || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_RELEASED) || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_RELEASED) || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_RELEASED) || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_RELEASED) || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_RELEASED) || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_RELEASED)
|| (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_RELEASED); || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_RELEASED);
} }
inline inline
bool inputs_are_down( bool inputs_are_down(
const InputKey* state_keys, const InputKey* active_keys,
int16 key0, int16 key1 = 0, int16 key2 = 0, int16 key3 = 0, int16 key4 = 0 int16 key0, int16 key1 = 0, int16 key2 = 0, int16 key3 = 0, int16 key4 = 0
) { ) {
return (key0 != 0 && input_is_down(state_keys, key0)) return (key0 != 0 && input_is_down(active_keys, key0))
&& (key1 == 0 || input_is_down(state_keys, key1)) && (key1 == 0 || input_is_down(active_keys, key1))
&& (key2 == 0 || input_is_down(state_keys, key2)) && (key2 == 0 || input_is_down(active_keys, key2))
&& (key3 == 0 || input_is_down(state_keys, key3)) && (key3 == 0 || input_is_down(active_keys, key3))
&& (key4 == 0 || input_is_down(state_keys, key4)); && (key4 == 0 || input_is_down(active_keys, key4));
} }
void input_add_callback(InputMapping* mapping, uint8 hotkey, InputCallback callback) void input_add_callback(InputMapping* mapping, uint8 hotkey, InputCallback callback)
{ {
mapping->callbacks[hotkey] = callback; mapping->hotkeys[hotkey].callback = callback;
} }
// We are binding hotkeys bi-directional // We are binding hotkeys bi-directional:
// Which keys are required for a certain hotkey
// What are the hotkeys a key can trigger
void void
input_add_hotkey( input_add_hotkey(
InputMapping* mapping, uint8 hotkey, InputMapping* mapping, uint8 hotkey,
int32 key0, int32 key1 = 0, int32 key2 = 0 int16 key0, int16 key1 = 0, int16 key2 = 0,
KeyPressType press_type = KEY_PRESS_TYPE_PRESSED
) )
{ {
int32 count = 0; int32 count = 0;
mapping->hotkeys[(hotkey - 1)].key_state = press_type;
// Define required keys for hotkey // Define required keys for hotkey
if (key0 != 0) { // Note: -1 since the hotkeys always MUST start at 1 (0 is a special value for empty)
if (key0) {
mapping->hotkeys[(hotkey - 1)].scan_codes[count++] = key0;
key0 = OMS_ABS_INT16(key0);
}
if (key1) {
// Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty) // Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty)
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION] = (int16) key0; mapping->hotkeys[(hotkey - 1)].scan_codes[count++] = key1;
++count; key1 = OMS_ABS_INT16(key1);
} }
if (key1 != 0) { if (key2) {
// Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty) // Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty)
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + count] = (int16) key1; mapping->hotkeys[(hotkey - 1)].scan_codes[count++] = key2;
++count; key2 = OMS_ABS_INT16(key2);
}
if (key2 != 0) {
// Note: -1 since the hotkeys MUST start at 1 (0 is a special value for empty)
mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + count] = (int16) key2;
}
if (key0 < 0) {
key0 *= -1;
}
if (key1 < 0) {
key1 *= -1;
}
if (key2 < 0) {
key2 *= -1;
}
int32 key0_offset = ((bool) (key0 & INPUT_KEYBOARD_PREFIX)) * MAX_MOUSE_KEYS
+ ((bool) (key0 & INPUT_CONTROLLER_PREFIX)) * (MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS);
int32 key1_offset = ((bool) (key1 & INPUT_KEYBOARD_PREFIX)) * MAX_MOUSE_KEYS
+ ((bool) (key1 & INPUT_CONTROLLER_PREFIX)) * (MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS);
int32 key2_offset = ((bool) (key2 & INPUT_KEYBOARD_PREFIX)) * MAX_MOUSE_KEYS
+ ((bool) (key2 & INPUT_CONTROLLER_PREFIX)) * (MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS);
key0 = (key0 & ~(INPUT_KEYBOARD_PREFIX | INPUT_CONTROLLER_PREFIX));
key1 = (key1 & ~(INPUT_KEYBOARD_PREFIX | INPUT_CONTROLLER_PREFIX));
key2 = (key2 & ~(INPUT_KEYBOARD_PREFIX | INPUT_CONTROLLER_PREFIX));
// Bind key to hotkey
for (int32 i = 0; i < MAX_KEY_TO_HOTKEY; ++i) {
if (key0 == 0 && key1 == 0 && key2 == 0) {
break;
}
if (key0 != 0 && mapping->keys[(key0 + key0_offset - 1) * MAX_KEY_TO_HOTKEY + i] == 0) {
mapping->keys[(key0 + key0_offset - 1) * MAX_KEY_TO_HOTKEY + i] = hotkey;
key0 = 0; // prevent adding same key again
}
if (key1 != 0 && mapping->keys[(key1 + key1_offset - 1) * MAX_KEY_TO_HOTKEY + i] == 0) {
mapping->keys[(key1 + key1_offset - 1) * MAX_KEY_TO_HOTKEY + i] = hotkey;
key1 = 0; // prevent adding same key again
}
if (key2 != 0 && mapping->keys[(key2 + key2_offset - 1) * MAX_KEY_TO_HOTKEY + i] == 0) {
mapping->keys[(key2 + key2_offset - 1) * MAX_KEY_TO_HOTKEY + i] = hotkey;
key2 = 0; // prevent adding same key again
}
} }
} }
inline inline
bool hotkey_is_active(const uint8* state_hotkeys, uint8 hotkey) bool hotkey_is_active(const uint16* active_hotkeys, uint16 hotkey)
{ {
return state_hotkeys[0] == hotkey return active_hotkeys[0] == hotkey
|| state_hotkeys[1] == hotkey || active_hotkeys[1] == hotkey
|| state_hotkeys[2] == hotkey || active_hotkeys[2] == hotkey
|| state_hotkeys[3] == hotkey || active_hotkeys[3] == hotkey
|| state_hotkeys[4] == hotkey; || active_hotkeys[4] == hotkey;
} }
// similar to hotkey_is_active but instead of just performing a lookup in the input_hotkey_state created results // similar to hotkey_is_active but instead of just performing a lookup in the input_hotkey_state created results
// this is actively checking the current input state (not the hotkey state) // this is actively checking the current input state (not the hotkey state)
inline inline
bool hotkey_keys_are_active(const InputKey* state_keys, const InputMapping* mapping, uint8 hotkey) bool hotkey_keys_are_active(const InputKey* active_keys, const InputMapping* mapping, uint16 hotkey)
{ {
int16 key0 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION]; int16 key0 = mapping->hotkeys[(hotkey - 1)].scan_codes[0];
int16 key1 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 1]; int16 key1 = mapping->hotkeys[(hotkey - 1)].scan_codes[1];
int16 key2 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 2]; int16 key2 = mapping->hotkeys[(hotkey - 1)].scan_codes[2];
if (!key0 && !key1 && !key2) {
return false;
}
// This may seem a little bit confusing but we don't care if a input key is down or up // This may seem a little bit confusing but we don't care if a input key is down or up
// Any state means it was used recently BUT NOT YET HANDLED // Any state means it was used recently BUT NOT YET HANDLED
@ -420,41 +383,43 @@ bool hotkey_keys_are_active(const InputKey* state_keys, const InputMapping* mapp
// Therefore, if a key has a state -> treat it as if active // Therefore, if a key has a state -> treat it as if active
// The code below also allows optional keys which have a negative sign (at least one of the optional keys must be valid) // The code below also allows optional keys which have a negative sign (at least one of the optional keys must be valid)
bool is_active = input_action_exists(state_keys, (int16) OMS_ABS(key0)); bool is_active = input_action_exists(active_keys, OMS_ABS_INT16(key0), mapping->hotkeys[(hotkey - 1)].key_state);
if ((!is_active && (key0 > 0 || key1 >= 0)) || (is_active && key0 < 0)) { if ((!is_active && (key0 > 0 || key1 >= 0)) || (is_active && key0 < 0) || (key1 == 0 && key2 == 0)) {
return is_active; return is_active;
} }
is_active = input_action_exists(state_keys, (int16) OMS_ABS(key1)); is_active = input_action_exists(active_keys, OMS_ABS_INT16(key1), mapping->hotkeys[(hotkey - 1)].key_state);
if ((!is_active && (key1 > 0 || key2 >= 0)) || (is_active && key1 < 0)) { if ((!is_active && (key1 > 0 || key2 >= 0)) || (is_active && key1 < 0) || (key2 == 0)) {
return is_active; return is_active;
} }
return input_action_exists(state_keys, (int16) OMS_ABS(key2)); return input_action_exists(active_keys, OMS_ABS_INT16(key2), mapping->hotkeys[(hotkey - 1)].key_state);
} }
inline inline
void input_set_state(InputKey* state_keys, InputKey* __restrict new_key) void input_set_state(InputKey* __restrict active_keys, const InputKey* __restrict new_key)
{ {
InputKey* free_state = NULL; InputKey* free_state = NULL;
bool action_required = true;
for (int32 i = 0; i < MAX_KEY_STATES; ++i) { // Insert new key state or change if key already exists
if (!free_state && state_keys[i].key_id == 0) { for (int32 i = 0; i < MAX_KEY_PRESS_TYPES; ++i) {
free_state = &state_keys[i]; if (!free_state && active_keys[i].scan_code == 0) {
} else if (state_keys[i].key_id == new_key->key_id) { free_state = &active_keys[i];
state_keys[i].key_state = new_key->key_state; } else if (active_keys[i].scan_code == new_key->scan_code) {
state_keys[i].value += new_key->value; active_keys[i].key_state = new_key->key_state;
state_keys[i].time = new_key->time; active_keys[i].value += new_key->value;
action_required = false; active_keys[i].time = new_key->time;
return;
} }
} }
if (!action_required || !free_state) { if (!free_state) {
return; return;
} }
free_state->key_id = new_key->key_id; free_state->scan_code = new_key->scan_code;
free_state->virtual_code = new_key->virtual_code;
free_state->key_state = new_key->key_state; free_state->key_state = new_key->key_state;
free_state->value = new_key->value; free_state->value = new_key->value;
free_state->time = new_key->time; free_state->time = new_key->time;
@ -470,15 +435,15 @@ void input_set_controller_state(Input* input, ControllerInput* controller, uint6
{ {
// Check active keys that might need to be set to inactive // Check active keys that might need to be set to inactive
for (int32 i = 0; i < MAX_KEY_PRESSES; ++i) { for (int32 i = 0; i < MAX_KEY_PRESSES; ++i) {
if ((input->state.state_keys[i].key_id & INPUT_CONTROLLER_PREFIX) if ((input->state.active_keys[i].scan_code & INPUT_CONTROLLER_PREFIX)
&& input->state.state_keys[i].key_state != KEY_STATE_RELEASED && input->state.active_keys[i].key_state != KEY_PRESS_TYPE_RELEASED
) { ) {
uint32 key_id = input->state.state_keys[i].key_id & ~INPUT_CONTROLLER_PREFIX; uint32 scan_code = input->state.active_keys[i].scan_code & ~INPUT_CONTROLLER_PREFIX;
if ((controller->is_analog[key_id] && OMS_ABS(controller->button[key_id]) < input->deadzone) if ((controller->is_analog[scan_code] && OMS_ABS_INT8(controller->button[scan_code]) < input->deadzone)
|| (!controller->is_analog[key_id] && controller->button[key_id] == 0) || (!controller->is_analog[scan_code] && controller->button[scan_code] == 0)
) { ) {
input->state.state_keys[i].key_state = KEY_STATE_RELEASED; input->state.active_keys[i].key_state = KEY_PRESS_TYPE_RELEASED;
} }
} }
} }
@ -486,28 +451,28 @@ void input_set_controller_state(Input* input, ControllerInput* controller, uint6
// Special keys // Special keys
// @todo this code means we cannot change this behavior (e.g. swap mouse view to dpad, swap sticks, ...) // @todo this code means we cannot change this behavior (e.g. swap mouse view to dpad, swap sticks, ...)
// @todo This is also not very general, maybe we can fix it like we did with analog vs digital key (instead of bool flag maybe bit flag) // @todo This is also not very general, maybe we can fix it like we did with analog vs digital key (instead of bool flag maybe bit flag)
if (OMS_ABS(controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL]) > input->deadzone) { if (OMS_ABS_INT8(controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL]) > input->deadzone) {
input->state.dx += controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] / 8; input->state.dx += controller->button[CONTROLLER_BUTTON_STICK_RIGHT_HORIZONTAL] / 8;
input->state_change_mouse = true; input->general_states |= INPUT_STATE_GENERAL_MOUSE_CHANGE;
} else { } else {
input->state.dx = 0; input->state.dx = 0;
} }
if (OMS_ABS(controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL]) > input->deadzone) { if (OMS_ABS_INT8(controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL]) > input->deadzone) {
input->state.dy += controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] / 8; input->state.dy += controller->button[CONTROLLER_BUTTON_STICK_RIGHT_VERTICAL] / 8;
input->state_change_mouse = true; input->general_states |= INPUT_STATE_GENERAL_MOUSE_CHANGE;
} else { } else {
input->state.dy = 0; input->state.dy = 0;
} }
if (OMS_ABS(controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL]) > input->deadzone) { if (OMS_ABS_INT8(controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL]) > input->deadzone) {
input->state.dx2 += controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] / 8; input->state.dx2 += controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] / 8;
// @todo needs state change flag like mouse?! // @todo needs state change flag like mouse?!
} else { } else {
input->state.dx2 = 0; input->state.dx2 = 0;
} }
if (OMS_ABS(controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL]) > input->deadzone) { if (OMS_ABS_INT8(controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL]) > input->deadzone) {
input->state.dy2 += controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] / 8; input->state.dy2 += controller->button[CONTROLLER_BUTTON_STICK_LEFT_HORIZONTAL] / 8;
// @todo needs state change flag like mouse?! // @todo needs state change flag like mouse?!
} else { } else {
@ -519,11 +484,11 @@ void input_set_controller_state(Input* input, ControllerInput* controller, uint6
InputKey keys[5]; InputKey keys[5];
for (uint16 i = 0; i < 32; ++i) { for (uint16 i = 0; i < 32; ++i) {
if ((controller->is_analog[i] && OMS_ABS(controller->button[i]) > input->deadzone) if ((controller->is_analog[i] && OMS_ABS_INT8(controller->button[i]) > input->deadzone)
|| (!controller->is_analog[i] && controller->button[i] != 0) || (!controller->is_analog[i] && controller->button[i] != 0)
) { ) {
keys[count].key_id = i | INPUT_CONTROLLER_PREFIX; keys[count].scan_code = i | INPUT_CONTROLLER_PREFIX;
keys[count].key_state = KEY_STATE_PRESSED; keys[count].key_state = KEY_PRESS_TYPE_PRESSED;
keys[count].value = controller->button[i]; keys[count].value = controller->button[i];
keys[count].time = time; keys[count].time = time;
@ -533,102 +498,117 @@ void input_set_controller_state(Input* input, ControllerInput* controller, uint6
if (count > 0) { if (count > 0) {
for (int32 i = 0; i < count; ++i) { for (int32 i = 0; i < count; ++i) {
input_set_state(input->state.state_keys, &keys[i]); input_set_state(input->state.active_keys, &keys[i]);
} }
} }
input->state_change_button = true; input->general_states |= INPUT_STATE_GENERAL_BUTTON_CHANGE;
} }
void void input_hotkey_state(Input* input)
input_hotkey_state(Input* input)
{ {
uint8 old_hotkeys[MAX_KEY_PRESSES];
InputState* state = &input->state; InputState* state = &input->state;
memset(state->active_hotkeys, 0, sizeof(uint16) * MAX_KEY_PRESSES);
memcpy(old_hotkeys, state->state_hotkeys, sizeof(uint8) * MAX_KEY_PRESSES); // Check if we have any active keys
if (memcmp(state->active_keys, ((byte *) state->active_keys) + 1, sizeof(state->active_keys) - 1) == 0) {
input_clean_state(state->active_keys);
return;
}
memset(state->state_hotkeys, 0, sizeof(uint8) * MAX_KEY_PRESSES); // Check typing mode
if (input->general_states & INPUT_STATE_GENERAL_TYPING_MODE) {
// @todo If this function becomes threaded we must maintain the input characters as a persistent state
int32 input_characters = 0;
memset(input->characters, 0, sizeof(uint32) * ARRAY_COUNT(input->characters));
int32 active_hotkeys = 0; // Create keyboard state array
byte keyboard_state[256] = {};
// Check every key down state for (int32 key_state = 0; key_state < MAX_KEY_PRESS_TYPES; ++key_state) {
for (int key_state = 0; key_state < MAX_KEY_STATES; ++key_state) { if (state->active_keys[key_state].scan_code == 0
if (state->state_keys[key_state].key_id == 0 || state->active_keys[key_state].key_state == KEY_PRESS_TYPE_RELEASED
|| state->state_keys[key_state].key_state == KEY_STATE_RELEASED
) { ) {
// no key defined for this down state // no key defined for this down state
continue; continue;
} }
// Is a key defined for this state AND is at least one hotkey defined for this key keyboard_state[state->active_keys[key_state].virtual_code & 0x00FF] = 0x80;
// If no hotkey is defined we don't care }
// Careful, remember MAX_MOUSE_KEYS offset
InputKey* key = &state->state_keys[key_state];
int32 internal_key_id = (key->key_id & ~(INPUT_KEYBOARD_PREFIX | INPUT_CONTROLLER_PREFIX))
+ ((bool) (key->key_id & INPUT_KEYBOARD_PREFIX)) * MAX_MOUSE_KEYS
+ ((bool) (key->key_id & INPUT_CONTROLLER_PREFIX)) * (MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS);
// Handle 2 input devices (1 = keyboard + mouse, 2 = controller) // Check if all keys result in text, if not -> is potential hotkey -> shouldn't output any text
// @performance Could it make sense to only loop over one mapping (create a pointer that references the correct mapping) for (int32 key_state = 0; key_state < MAX_KEY_PRESS_TYPES; ++key_state) {
// We then swap this pointer whenever we detect a input from keyboard+mouse vs controller if ((input->general_states & INPUT_STATE_GENERAL_TYPING_MODE)
// This would allow us even to add context specific mappings && (state->active_keys[key_state].scan_code & INPUT_KEYBOARD_PREFIX)
for (int32 i = 0; i < 2; ++i) { && state->active_keys[key_state].key_state != KEY_PRESS_TYPE_RELEASED
InputMapping* mapping;
if (i == 0) {
mapping = &input->input_mapping1;
} else if ((input->handle_controller || input->direct_controller)
&& key->key_id > INPUT_CONTROLLER_PREFIX
) { ) {
mapping = &input->input_mapping2; if (input_characters >= ARRAY_COUNT(input->characters)) {
} else { break;
continue;
} }
if (mapping->keys[(internal_key_id - 1) * MAX_KEY_TO_HOTKEY] == 0) { uint32 code = key_to_unicode(
// no possible hotkey associated with this key state->active_keys[key_state].scan_code & 0x00FF,
continue; state->active_keys[key_state].virtual_code & 0x00FF,
keyboard_state
);
// Is the pressed key a keyboard input
if (!code) {
// Is not text -> we have to reset characters
memset(input->characters, 0, sizeof(uint32) * input_characters);
input_characters = 0;
break;
} }
const uint8* hotkeys_for_key = mapping->keys + (internal_key_id - 1) * MAX_KEY_TO_HOTKEY; input->characters[input_characters++] = code;
}
}
// Check every possible hotkey if (input_characters) {
// Since multiple input devices have their own button/key indices whe have to do this weird range handling for (int32 key_state = 0; key_state < MAX_KEY_PRESS_TYPES; ++key_state) {
for (int32 possible_hotkey_idx = 0; possible_hotkey_idx < MAX_KEY_TO_HOTKEY; ++possible_hotkey_idx) { state->active_keys[key_state].is_processed = true;
// We only support a slimited amount of active hotkeys state->active_keys[key_state].time = 0; // @todo fix
if (active_hotkeys >= MAX_KEY_PRESSES) { }
input_clean_state(state->active_keys);
return; return;
} }
}
// Hotkey already active int32 active_hotkeys = 0;
// @question Do we even need this? This shouldn't happen anyway?!
if (hotkey_is_active(state->state_hotkeys, hotkeys_for_key[possible_hotkey_idx])) { // Check every mapping
for (int32 i = 0; i < 2; ++i) {
InputMapping* mapping = i == 0 ? &input->input_mapping1 : &input->input_mapping2;
// Check all possible hotkeys if all of their required keys are active
for (int16 hotkey_idx = 1; hotkey_idx <= mapping->hotkey_count; ++hotkey_idx) {
// We only support a limited amount of active hotkeys
if (active_hotkeys >= MAX_KEY_PRESSES) {
hotkey_idx = mapping->hotkey_count + 1;
i = 2;
break;
}
if (hotkey_is_active(state->active_hotkeys, hotkey_idx),
!hotkey_keys_are_active(state->active_keys, mapping, hotkey_idx)
) {
// Hotkey already active, we don't need to check if it needs to be activated
// Or not all keys for the hotkey are pressed or the KeyPressType is not the same
continue; continue;
} }
// store active hotkey, if it is not already active state->active_hotkeys[active_hotkeys++] = hotkey_idx;
bool is_pressed = hotkey_keys_are_active(state->state_keys, mapping, hotkeys_for_key[possible_hotkey_idx]);
if (!is_pressed) {
continue;
}
state->state_hotkeys[active_hotkeys] = hotkeys_for_key[possible_hotkey_idx];
++active_hotkeys;
// Run callback if defined // Run callback if defined
if (input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]] != 0 if (mapping->hotkeys[hotkey_idx].callback != 0) {
&& old_hotkeys[0] != hotkeys_for_key[possible_hotkey_idx] mapping->hotkeys[hotkey_idx].callback(input->callback_data);
&& old_hotkeys[1] != hotkeys_for_key[possible_hotkey_idx]
&& old_hotkeys[2] != hotkeys_for_key[possible_hotkey_idx]
&& old_hotkeys[3] != hotkeys_for_key[possible_hotkey_idx]
&& old_hotkeys[4] != hotkeys_for_key[possible_hotkey_idx]
) {
input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]](input->callback_data);
}
} }
} }
} }
input_clean_state(state->active_keys);
// @bug how to handle priority? e.g. there might be a hotkey for 1 and one for alt+1 // @bug how to handle priority? e.g. there might be a hotkey for 1 and one for alt+1
// in this case only the hotkey for alt+1 should be triggered // in this case only the hotkey for alt+1 should be triggered
// @bug how to handle other conditions besides buttons pressed together? some hotkeys are only available in certain situations // @bug how to handle other conditions besides buttons pressed together? some hotkeys are only available in certain situations
@ -639,10 +619,11 @@ input_hotkey_state(Input* input)
// It doesn't always happen but you can test it rather consistently within a couple of seconds // It doesn't always happen but you can test it rather consistently within a couple of seconds
} }
bool input_key_is_longpress(InputState* state, uint16 key, uint64 time, f32 dt = 0.0f) { // @todo We probably need a way to unset a specific key and hotkey after processing it
for (int32 i = 0; i < MAX_KEY_STATES; ++i) { bool input_key_is_longpress(const InputState* state, int16 key, uint64 time, f32 dt = 0.0f) {
if (state->state_keys[i].key_id == key) { for (int32 i = 0; i < MAX_KEY_PRESS_TYPES; ++i) {
return (f32) (time - state->state_keys[i].time) / 1000.0f >= (dt == 0.0f ? INPUT_LONG_PRESS_DURATION : dt); if (state->active_keys[i].scan_code == key) {
return (f32) (time - state->active_keys[i].time) / 1000.0f >= (dt == 0.0f ? INPUT_LONG_PRESS_DURATION : dt);
} }
} }
@ -650,10 +631,10 @@ bool input_key_is_longpress(InputState* state, uint16 key, uint64 time, f32 dt =
} }
// @todo I wrote this code at 9am after staying awake for the whole night and that is how that code looks like... fix it! // @todo I wrote this code at 9am after staying awake for the whole night and that is how that code looks like... fix it!
bool input_hotkey_is_longpress(Input* input, uint8 hotkey, uint64 time, f32 dt = 0.0f) { bool input_hotkey_is_longpress(const Input* input, uint8 hotkey, uint64 time, f32 dt = 0.0f) {
bool is_longpress = false; bool is_longpress = false;
for (int32 i = 0; i < MAX_KEY_PRESSES; ++i) { for (int32 i = 0; i < MAX_KEY_PRESSES; ++i) {
if (input->state.state_hotkeys[i] != hotkey) { if (input->state.active_hotkeys[i] != hotkey) {
continue; continue;
} }
@ -662,8 +643,8 @@ bool input_hotkey_is_longpress(Input* input, uint8 hotkey, uint64 time, f32 dt =
for (int32 j = 0; j < MAX_HOTKEY_COMBINATION; ++j) { for (int32 j = 0; j < MAX_HOTKEY_COMBINATION; ++j) {
bool potential_miss = true; bool potential_miss = true;
bool both_empty = false; bool both_empty = false;
if (input->input_mapping1.hotkeys[hotkey * MAX_HOTKEY_COMBINATION + j] > 0) { if (input->input_mapping1.hotkeys[hotkey].scan_codes[j] > 0) {
if(!input_key_is_longpress(&input->state, input->input_mapping1.hotkeys[hotkey + j], time, dt)) { if(!input_key_is_longpress(&input->state, input->input_mapping1.hotkeys[hotkey].scan_codes[j], time, dt)) {
potential_miss = true; potential_miss = true;
} else { } else {
potential_miss = false; potential_miss = false;
@ -676,8 +657,8 @@ bool input_hotkey_is_longpress(Input* input, uint8 hotkey, uint64 time, f32 dt =
continue; continue;
} }
if (input->input_mapping2.hotkeys[hotkey * MAX_HOTKEY_COMBINATION + j] > 0) { if (input->input_mapping2.hotkeys[hotkey].scan_codes[j] > 0) {
if(!input_key_is_longpress(&input->state, input->input_mapping2.hotkeys[hotkey + j], time, dt)) { if(!input_key_is_longpress(&input->state, input->input_mapping2.hotkeys[hotkey].scan_codes[j], time, dt)) {
potential_miss = true; potential_miss = true;
} else { } else {
potential_miss = false; potential_miss = false;
@ -697,4 +678,48 @@ bool input_hotkey_is_longpress(Input* input, uint8 hotkey, uint64 time, f32 dt =
return is_longpress; return is_longpress;
} }
uint32 input_get_typed_character(InputState* state, uint64 time, uint64 dt)
{
byte keyboard_state[256] = {};
for (int32 key_state = 0; key_state < MAX_KEY_PRESS_TYPES; ++key_state) {
if (state->active_keys[key_state].scan_code == 0
|| state->active_keys[key_state].key_state == KEY_PRESS_TYPE_RELEASED
) {
// no key defined for this down state
continue;
}
keyboard_state[state->active_keys[key_state].virtual_code & 0x00FF] = 0x80;
}
for (int32 key_state = 0; key_state < MAX_KEY_PRESS_TYPES; ++key_state) {
if (state->active_keys[key_state].scan_code == 0
|| (state->active_keys[key_state].is_processed
&& state->active_keys[key_state].time - time <= dt)
) {
// no key defined for this down state
// key is already released
// key was already processed and is not yet eligible for continuous output
continue;
}
uint32 code = key_to_unicode(
state->active_keys[key_state].scan_code & 0x00FF,
state->active_keys[key_state].virtual_code & 0x00FF,
keyboard_state
);
if (code) {
// We are not outputting a repeat character multiple times in low fps situations.
// It is annoying as a user to suddenly have 10s of repeated character just because the game lagged
state->active_keys[key_state].is_processed = true;
state->active_keys[key_state].time = time;
return code;
}
}
return 0;
}
#endif #endif

View File

@ -8,7 +8,6 @@
#include "TimingStat.h" #include "TimingStat.h"
#include "../utils/StringUtils.h" #include "../utils/StringUtils.h"
#include "../utils/TestUtils.h" #include "../utils/TestUtils.h"
#include "../utils/MathUtils.h"
#include "../thread/Atomic.h" #include "../thread/Atomic.h"
// Required for rdtsc(); // Required for rdtsc();
@ -69,34 +68,24 @@ void log_to_file()
#if _WIN32 #if _WIN32
DWORD written; DWORD written;
if (!WriteFile( WriteFile(
debug_container->log_fp, debug_container->log_fp,
(char *) debug_container->log_memory.memory, (char *) debug_container->log_memory.memory,
(uint32) debug_container->log_memory.pos - 1, (uint32) debug_container->log_memory.pos,
&written, &written,
NULL NULL
)) { );
CloseHandle(debug_container->log_fp);
}
#else #else
if (debug_container->log_fp < 0) { if (debug_container->log_fp < 0) {
return; return;
} }
if (!write( write(
debug_container->log_fp, debug_container->log_fp,
(char *) debug_container->log_memory.memory, (char *) debug_container->log_memory.memory,
(uint32) debug_container->log_memory.pos - 1 (uint32) debug_container->log_memory.pos
)) { );
close(debug_container->log_fp);
}
#endif #endif
memset(debug_container->log_memory.memory, 0, debug_container->log_memory.size);
// reset log position to start of memory pool
debug_container->log_memory.pos = 0;
debug_container->log_memory.start = 0;
} }
// IMPORTANT: This function should only be called when you actually use this data // IMPORTANT: This function should only be called when you actually use this data
@ -184,9 +173,8 @@ void log_counter(int32 id, int64 value)
atomic_set_acquire(&debug_container->counter[id], value); atomic_set_acquire(&debug_container->counter[id], value);
} }
// @todo don't use a pointer to this should be in a global together with other logging data (see Log.h)
inline inline
DebugMemory* debug_memory_find(uint64 start) DebugMemory* debug_memory_find(uintptr_t start)
{ {
for (uint64 i = 0; i < debug_container->dmc.memory_size; ++i) { for (uint64 i = 0; i < debug_container->dmc.memory_size; ++i) {
if (debug_container->dmc.memory_stats[i].start <= start if (debug_container->dmc.memory_stats[i].start <= start
@ -199,7 +187,7 @@ DebugMemory* debug_memory_find(uint64 start)
return NULL; return NULL;
} }
void debug_memory_init(uint64 start, uint64 size) void debug_memory_init(uintptr_t start, uint64 size)
{ {
if (!start || !debug_container) { if (!start || !debug_container) {
return; return;
@ -231,7 +219,7 @@ void debug_memory_init(uint64 start, uint64 size)
++dmc->memory_element_idx; ++dmc->memory_element_idx;
} }
void debug_memory_log(uint64 start, uint64 size, int32 type, const char* function) void debug_memory_log(uintptr_t start, uint64 size, int32 type, const char* function)
{ {
if (!start || !debug_container) { if (!start || !debug_container) {
return; return;
@ -263,7 +251,7 @@ void debug_memory_log(uint64 start, uint64 size, int32 type, const char* functio
} }
} }
void debug_memory_reserve(uint64 start, uint64 size, int32 type, const char* function) void debug_memory_reserve(uintptr_t start, uint64 size, int32 type, const char* function)
{ {
if (!start || !debug_container) { if (!start || !debug_container) {
return; return;
@ -290,7 +278,7 @@ void debug_memory_reserve(uint64 start, uint64 size, int32 type, const char* fun
} }
// undo reserve // undo reserve
void debug_memory_free(uint64 start, uint64 size) void debug_memory_free(uintptr_t start, uint64 size)
{ {
if (!start || !debug_container) { if (!start || !debug_container) {
return; return;
@ -331,124 +319,118 @@ void debug_memory_reset()
} }
// @bug This probably requires thread safety // @bug This probably requires thread safety
byte* log_get_memory(uint64 size, byte aligned = 4, bool zeroed = false) byte* log_get_memory()
{ {
if (!debug_container) {
return 0;
}
LogMemory* log_mem = &debug_container->log_memory; LogMemory* log_mem = &debug_container->log_memory;
ASSERT_SIMPLE(size <= log_mem->size); if (log_mem->pos + MAX_LOG_LENGTH > log_mem->size) {
if (aligned > 1) {
uintptr_t address = (uintptr_t) log_mem->memory;
log_mem->pos += (aligned - ((address + log_mem->pos) & (aligned - 1))) % aligned;
}
size = ROUND_TO_NEAREST(size, aligned);
if (log_mem->pos + size > log_mem->size) {
log_mem->pos = 0; log_mem->pos = 0;
if (aligned > 1) {
uintptr_t address = (uintptr_t) log_mem->memory;
log_mem->pos += (aligned - ((address + log_mem->pos) & (aligned - 1))) % aligned;
}
} }
byte* offset = (byte *) (log_mem->memory + log_mem->pos); byte* offset = (byte *) (log_mem->memory + log_mem->pos);
if (zeroed) { memset((void *) offset, 0, MAX_LOG_LENGTH);
memset((void *) offset, 0, size);
}
log_mem->pos += size; log_mem->pos += MAX_LOG_LENGTH;
return offset; return offset;
} }
// @todo add file name, function name and function line void log(const char* str, bool should_log, const char* file, const char* function, int32 line)
void log(const char* str, bool should_log, bool save, const char* file, const char* function, int32 line)
{ {
if (!should_log || !debug_container) { if (!should_log || !debug_container) {
return; return;
} }
size_t str_len = OMS_MIN(strlen(str), MAX_LOG_LENGTH - 128); int64 len = strlen(str);
size_t file_len = strlen(file); while (len > 0) {
size_t function_len = strlen(function); LogMessage* msg = (LogMessage *) log_get_memory();
char line_str[14]; // Fill file
uint_to_str(line, line_str); msg->file = file;
msg->function = function;
msg->line = line;
msg->message = (char *) (msg + 1);
size_t line_len = strlen(line_str); int32 message_length = (int32) OMS_MIN(MAX_LOG_LENGTH - sizeof(LogMessage) - 1, len);
ASSERT_SIMPLE(str_len + file_len + function_len + line_len + 3 < MAX_LOG_LENGTH); memcpy(msg->message, str, message_length);
msg->message[message_length] = '\0';
str += message_length;
len -= MAX_LOG_LENGTH - sizeof(LogMessage);
char* temp = (char *) log_get_memory(str_len + file_len + function_len + line_len + 3 + 1); if (debug_container->log_memory.size - debug_container->log_memory.pos < MAX_LOG_LENGTH) {
memcpy(temp, file, file_len);
temp[file_len] = ';';
memcpy(&temp[file_len], function, function_len);
temp[file_len + 1 + function_len] = ';';
memcpy(&temp[file_len + 1 + function_len], line_str, line_len);
temp[file_len + 1 + function_len + 1 + line_len] = ';';
memcpy(&temp[file_len + 1 + function_len + 1 + line_len + 1], str, str_len);
temp[file_len + 1 + function_len + 1 + line_len + 1 + str_len] = '\0';
if (save || debug_container->log_memory.size - debug_container->log_memory.pos < MAX_LOG_LENGTH) {
log_to_file(); log_to_file();
debug_container->log_memory.pos = 0;
}
} }
} }
void log(const char* format, LogDataType data_type, void* data, bool should_log, bool save, const char* file, const char* function, int32 line) void log(const char* format, LogDataArray data, bool should_log, const char* file, const char* function, int32 line)
{ {
ASSERT_SIMPLE(strlen(format) + strlen(file) + strlen(function) + 50 < MAX_LOG_LENGTH);
if (!should_log || !debug_container) { if (!should_log || !debug_container) {
return; return;
} }
if (data_type == LOG_DATA_VOID) { if (data.data[0].type == LOG_DATA_VOID) {
log(format, should_log, save, file, function, line); log(format, should_log, file, function, line);
return;
} }
char* temp = (char *) log_get_memory(MAX_LOG_LENGTH); LogMessage* msg = (LogMessage *) log_get_memory();
msg->file = file;
msg->function = function;
msg->line = line;
msg->message = (char *) (msg + 1);
switch (data_type) { char temp_format[MAX_LOG_LENGTH];
str_copy_short(msg->message, format);
for (int32 i = 0; i < LOG_DATA_ARRAY; ++i) {
if (data.data[i].type == LOG_DATA_VOID) {
break;
}
str_copy_short(temp_format, msg->message);
switch (data.data[i].type) {
case LOG_DATA_BYTE: {
sprintf_fast_iter(msg->message, temp_format, (int32) *((byte *) data.data[i].value));
} break;
case LOG_DATA_INT32: { case LOG_DATA_INT32: {
sprintf(temp, format, *((int32 *) data)); sprintf_fast_iter(msg->message, temp_format, *((int32 *) data.data[i].value));
} break; } break;
case LOG_DATA_UINT32: { case LOG_DATA_UINT32: {
sprintf(temp, format, *((uint32 *) data)); sprintf_fast_iter(msg->message, temp_format, *((uint32 *) data.data[i].value));
} break; } break;
case LOG_DATA_INT64: { case LOG_DATA_INT64: {
sprintf(temp, format, *((int64 *) data)); sprintf_fast_iter(msg->message, temp_format, *((int64 *) data.data[i].value));
} break; } break;
case LOG_DATA_UINT64: { case LOG_DATA_UINT64: {
sprintf(temp, format, *((uint64 *) data)); sprintf_fast_iter(msg->message, temp_format, *((uint64 *) data.data[i].value));
} break; } break;
case LOG_DATA_CHAR: { case LOG_DATA_CHAR: {
sprintf(temp, format, *((char *) data)); sprintf_fast_iter(msg->message, temp_format, *((char *) data.data[i].value));
} break; } break;
case LOG_DATA_CHAR_STR: { case LOG_DATA_CHAR_STR: {
sprintf(temp, format, *((char *) data)); sprintf_fast_iter(msg->message, temp_format, (const char *) data.data[i].value);
} break; } break;
case LOG_DATA_FLOAT32: { case LOG_DATA_FLOAT32: {
sprintf(temp, format, *((f32 *) data)); sprintf_fast_iter(msg->message, temp_format, *((f32 *) data.data[i].value));
} break; } break;
case LOG_DATA_FLOAT64: { case LOG_DATA_FLOAT64: {
sprintf(temp, format, *((f64 *) data)); sprintf_fast_iter(msg->message, temp_format, *((f64 *) data.data[i].value));
} break; } break;
default: { default: {
UNREACHABLE(); UNREACHABLE();
} }
} }
}
if (save || debug_container->log_memory.size - debug_container->log_memory.pos < MAX_LOG_LENGTH) { if (debug_container->log_memory.size - debug_container->log_memory.pos < MAX_LOG_LENGTH) {
log_to_file(); log_to_file();
debug_container->log_memory.pos = 0;
} }
ASSERT_SIMPLE(false);
} }
#endif #endif

View File

@ -18,15 +18,56 @@
#include <windows.h> #include <windows.h>
#endif #endif
#ifndef MAX_LOG_LENGTH
#define MAX_LOG_LENGTH 256
#endif
#ifndef MAX_LOG_MESSAGES
#define MAX_LOG_MESSAGES 256
#endif
#ifndef LOG_LEVEL
#define LOG_LEVEL 0
#endif
#define LOG_DATA_ARRAY 5
enum LogDataType {
LOG_DATA_NONE,
LOG_DATA_VOID,
LOG_DATA_BYTE,
LOG_DATA_INT32,
LOG_DATA_UINT32,
LOG_DATA_INT64,
LOG_DATA_UINT64,
LOG_DATA_CHAR,
LOG_DATA_CHAR_STR,
LOG_DATA_FLOAT32,
LOG_DATA_FLOAT64
};
struct LogMemory { struct LogMemory {
byte* memory; byte* memory;
uint32 id;
uint64 size; uint64 size;
uint64 pos; uint64 pos;
uint32 alignment; };
uint64 start;
uint64 end; struct LogMessage {
const char* file;
const char* function;
int32 line;
uint64 time;
char* message;
};
struct LogData {
LogDataType type;
void* value;
};
struct LogDataArray{
LogData data[LOG_DATA_ARRAY];
}; };
struct DebugContainer { struct DebugContainer {

View File

@ -16,7 +16,7 @@
struct DebugMemoryRange { struct DebugMemoryRange {
int32 type; int32 type;
uint64 start; uintptr_t start;
uint64 size; uint64 size;
uint64 time; uint64 time;
@ -25,7 +25,7 @@ struct DebugMemoryRange {
struct DebugMemory { struct DebugMemory {
uint64 usage; uint64 usage;
uint64 start; uintptr_t start;
uint64 size; uint64 size;
uint64 action_idx; uint64 action_idx;
@ -42,10 +42,10 @@ struct DebugMemoryContainer {
}; };
#if DEBUG || INTERNAL #if DEBUG || INTERNAL
void debug_memory_init(uint64, uint64); void debug_memory_init(uintptr_t, uint64);
void debug_memory_log(uint64, uint64, int32, const char*); void debug_memory_log(uintptr_t, uint64, int32, const char*);
void debug_memory_reserve(uint64, uint64, int32, const char*); void debug_memory_reserve(uintptr_t, uint64, int32, const char*);
void debug_memory_free(uint64, uint64); void debug_memory_free(uintptr_t, uint64);
void debug_memory_reset(); void debug_memory_reset();
#define DEBUG_MEMORY_INIT(start, size) debug_memory_init((start), (size)) #define DEBUG_MEMORY_INIT(start, size) debug_memory_init((start), (size))

View File

@ -13,63 +13,37 @@
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "Debug.h" #include "Debug.h"
#ifndef MAX_LOG_LENGTH
#define MAX_LOG_LENGTH 1024
#endif
enum LogDataType {
LOG_DATA_VOID,
LOG_DATA_INT32,
LOG_DATA_UINT32,
LOG_DATA_INT64,
LOG_DATA_UINT64,
LOG_DATA_CHAR,
LOG_DATA_CHAR_STR,
LOG_DATA_FLOAT32,
LOG_DATA_FLOAT64
};
void log_to_file(); void log_to_file();
void log(const char* str, bool should_log, bool save, const char* file, const char* function, int32 line); void log(const char* str, bool should_log, const char* file, const char* function, int32 line);
void log(const char* format, LogDataType data_type, void* data, bool should_log, bool save, const char* file, const char* function, int32 line); void log(const char* format, LogDataArray data, bool should_log, const char* file, const char* function, int32 line);
void log_increment(int32, int64); void log_increment(int32, int64);
void log_counter(int32, int64); void log_counter(int32, int64);
#define LOG_PERFORMANCE_START(time_start) \ #define LOG(should_log, str) log((str), (should_log), __FILE__, __func__, __LINE__)
({ \ #define LOG_FORMAT(should_log, format, ...) log((format), LogDataArray{__VA_ARGS__}, (should_log), __FILE__, __func__, __LINE__)
time_start = __rdtsc(); \ #define LOG_TO_FILE() log_to_file()
})
#define LOG_PERFORMANCE_END(time_start) \ #if LOG_LEVEL == 2
({ \ #define LOG_LEVEL_1(format, ...) log((format), LogDataArray{__VA_ARGS__}, true, __FILE__, __func__, __LINE__)
printf("%ld\n", __rdtsc() - (time_start)); \ #define LOG_LEVEL_2(format, ...) log((format), LogDataArray{__VA_ARGS__}, true, __FILE__, __func__, __LINE__)
}) #elif LOG_LEVEL == 1
#define LOG_LEVEL_1(format, ...) log((format), LogDataArray{__VA_ARGS__}, true, __FILE__, __func__, __LINE__)
#define LOG_LEVEL_2(format, ...) ((void) 0)
#elif LOG_LEVEL == 0
#define LOG_LEVEL_1(format, ...) ((void) 0)
#define LOG_LEVEL_2(format, ...) ((void) 0)
#endif
#if (!DEBUG && !INTERNAL) || RELEASE #if (!DEBUG && !INTERNAL) || RELEASE
// Don't perform any logging at log level 0
#define LOG(str, should_log, save) log((str), (should_log), (save), __FILE__, __func__, __LINE__)
#define LOG_FORMAT(format, data_type, data, should_log, save) log((format), (data_type), (data), (should_log), (save), __FILE__, __func__, __LINE__)
#define LOG_TO_FILE() ((void) 0)
#define LOG_INCREMENT(a) ((void) 0) #define LOG_INCREMENT(a) ((void) 0)
#define LOG_INCREMENT_BY(a, b) ((void) 0) #define LOG_INCREMENT_BY(a, b) ((void) 0)
#define LOG_COUNTER(a, b) ((void) 0) #define LOG_COUNTER(a, b) ((void) 0)
#define RESET_COUNTER(a) ((void) 0) #define RESET_COUNTER(a) ((void) 0)
#else #else
#define LOG(str, should_log, save) log((str), (should_log), (save), __FILE__, __func__, __LINE__)
#define LOG_FORMAT(format, data_type, data, should_log, save) log((format), (data_type), (data), (should_log), (save), __FILE__, __func__, __LINE__)
#define LOG_TO_FILE() log_to_file()
#define LOG_INCREMENT(a) log_increment((a), 1) #define LOG_INCREMENT(a) log_increment((a), 1)
#define LOG_INCREMENT_BY(a, b) log_increment((a), (b)) #define LOG_INCREMENT_BY(a, b) log_increment((a), (b))
#define LOG_COUNTER(a, b) log_counter((a), (b)) #define LOG_COUNTER(a, b) log_counter((a), (b))
#define RESET_COUNTER(a) reset_counter((a)) #define RESET_COUNTER(a) reset_counter((a))
#endif #endif
#if DEBUG
#define DEBUG_LOG(str, should_log, save) log((str), (should_log), (save), __FILE__, __func__, __LINE__)
#define DEBUG_LOG_FORMAT(format, data_type, data, should_log, save) log((format), (data_type), (data), (should_log), (save), __FILE__, __func__, __LINE__)
#else
#define DEBUG_LOG(str, should_log, save) ((void) 0)
#define DEBUG_LOG_FORMAT(format, data_type, data, should_log, save) ((void) 0)
#endif
#endif #endif

View File

@ -12,7 +12,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "../../utils/MathUtils.h"
#include "../../utils/TestUtils.h" #include "../../utils/TestUtils.h"
#if ARM #if ARM
@ -345,7 +344,7 @@ void mat4_identity(__m128* matrix)
// https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula // https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
void mat4_rotation(f32* matrix, f32 x, f32 y, f32 z, f32 angle) void mat4_rotation(f32* matrix, f32 x, f32 y, f32 z, f32 angle)
{ {
ASSERT_SIMPLE(OMS_ABS(x * x + y * y + z * z - 1.0f) < 0.01); ASSERT_SIMPLE(OMS_ABS_F32(x * x + y * y + z * z - 1.0f) < 0.01);
// @todo replace with quaternions // @todo replace with quaternions
f32 s = sinf(angle); f32 s = sinf(angle);

View File

@ -9,8 +9,6 @@
#ifndef TOS_MATH_MATRIX_INT32_H #ifndef TOS_MATH_MATRIX_INT32_H
#define TOS_MATH_MATRIX_INT32_H #define TOS_MATH_MATRIX_INT32_H
#include "../../utils/MathUtils.h"
#if ARM #if ARM
#include "../../stdlib/IntrinsicsArm.h" #include "../../stdlib/IntrinsicsArm.h"
#else #else

View File

@ -9,8 +9,6 @@
#ifndef TOS_MATH_MATRIX_INT64_H #ifndef TOS_MATH_MATRIX_INT64_H
#define TOS_MATH_MATRIX_INT64_H #define TOS_MATH_MATRIX_INT64_H
#include "../../utils/MathUtils.h"
#if ARM #if ARM
#include "../../stdlib/IntrinsicsArm.h" #include "../../stdlib/IntrinsicsArm.h"
#else #else

View File

@ -10,7 +10,6 @@
#ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H #ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H
#define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H #define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H
#include "../../utils/MathUtils.h"
#include "../../utils/TestUtils.h" #include "../../utils/TestUtils.h"
#include "MatrixFloat32.h" #include "MatrixFloat32.h"
@ -97,7 +96,7 @@ void quaternion_to_euler(const v4_f32* __restrict quat, v3_f32* __restrict v) {
v->pitch = atan2f(sinp, cosp); v->pitch = atan2f(sinp, cosp);
// Check for gimbal lock // Check for gimbal lock
if (OMS_ABS(sinp) >= 0.9999f) { if (OMS_ABS_F32(sinp) >= 0.9999f) {
v->yaw = atan2f(quat->x * quat->z - quat->w * quat->y, quat->w * quat->x + quat->y * quat->z); v->yaw = atan2f(quat->x * quat->z - quat->w * quat->y, quat->w * quat->x + quat->y * quat->z);
v->roll = 0.0f; v->roll = 0.0f;
} else { } else {
@ -225,7 +224,7 @@ void quaternion_rotate_vector(v3_f32* __restrict vec, const v4_f32* __restrict q
inline inline
void quaternion_rotate_active(v4_f32* __restrict p, const v4_f32* __restrict quat, const v4_f32* __restrict quat_inv) void quaternion_rotate_active(v4_f32* __restrict p, const v4_f32* __restrict quat, const v4_f32* __restrict quat_inv)
{ {
//ASSERT_SIMPLE(OMS_ABS(x * x + y * y + z * z + w * z - 1.0f) < 0.01); //ASSERT_SIMPLE(OMS_ABS_F32(x * x + y * y + z * z + w * z - 1.0f) < 0.01);
v4_f32 p_tmp; v4_f32 p_tmp;
quaternion_multiply(&p_tmp, quat_inv, p); quaternion_multiply(&p_tmp, quat_inv, p);
@ -236,7 +235,7 @@ void quaternion_rotate_active(v4_f32* __restrict p, const v4_f32* __restrict qua
inline inline
void quaternion_rotate_passive(v4_f32* __restrict p, const v4_f32* __restrict quat, const v4_f32* __restrict quat_inv) void quaternion_rotate_passive(v4_f32* __restrict p, const v4_f32* __restrict quat, const v4_f32* __restrict quat_inv)
{ {
//ASSERT_SIMPLE(OMS_ABS(x * x + y * y + z * z + w * w - 1.0f) < 0.01); //ASSERT_SIMPLE(OMS_ABS_F32(x * x + y * y + z * z + w * w - 1.0f) < 0.01);
v4_f32 p_tmp; v4_f32 p_tmp;
quaternion_multiply(&p_tmp, quat, p); quaternion_multiply(&p_tmp, quat, p);

View File

@ -9,7 +9,6 @@
#ifndef TOS_MATH_MATRIX_VECTOR_FLOAT32_H #ifndef TOS_MATH_MATRIX_VECTOR_FLOAT32_H
#define TOS_MATH_MATRIX_VECTOR_FLOAT32_H #define TOS_MATH_MATRIX_VECTOR_FLOAT32_H
#include "../../utils/MathUtils.h"
#include "../../stdlib/Simd.h" #include "../../stdlib/Simd.h"
struct v3_f32_4 { struct v3_f32_4 {

View File

@ -9,7 +9,6 @@
#ifndef TOS_MATH_MATRIX_VECTOR_FLOAT64_H #ifndef TOS_MATH_MATRIX_VECTOR_FLOAT64_H
#define TOS_MATH_MATRIX_VECTOR_FLOAT64_H #define TOS_MATH_MATRIX_VECTOR_FLOAT64_H
#include "../../utils/MathUtils.h"
#include "../../stdlib/Simd.h" #include "../../stdlib/Simd.h"
#endif #endif

View File

@ -12,7 +12,6 @@
#include <immintrin.h> #include <immintrin.h>
#include <xmmintrin.h> #include <xmmintrin.h>
#include "../../utils/MathUtils.h"
#include "../../stdlib/Simd.h" #include "../../stdlib/Simd.h"
struct v3_int32_4 { struct v3_int32_4 {

View File

@ -12,7 +12,6 @@
#include <immintrin.h> #include <immintrin.h>
#include <xmmintrin.h> #include <xmmintrin.h>
#include "../../utils/MathUtils.h"
#include "../../stdlib/Simd.h" #include "../../stdlib/Simd.h"
struct v3_int64_2 { struct v3_int64_2 {

View File

@ -11,7 +11,6 @@
#include <string.h> #include <string.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
#include "../utils/EndianUtils.h" #include "../utils/EndianUtils.h"
#include "../utils/TestUtils.h" #include "../utils/TestUtils.h"
#include "../log/DebugMemory.h" #include "../log/DebugMemory.h"
@ -46,13 +45,15 @@ void buffer_alloc(BufferMemory* buf, uint64 size, int32 alignment = 64)
memset(buf->memory, 0, buf->size); memset(buf->memory, 0, buf->size);
DEBUG_MEMORY_INIT((uint64) buf->memory, size); DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size);
LOG_INCREMENT_BY(DEBUG_COUNTER_MEM_ALLOC, buf->size);
LOG_LEVEL_2("Allocated BufferMemory: %n B", {{LOG_DATA_UINT64, &buf->size}});
} }
inline inline
void buffer_free(BufferMemory* buf) void buffer_free(BufferMemory* buf)
{ {
DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->size); DEBUG_MEMORY_DELETE((uintptr_t) buf->memory, buf->size);
if (buf->alignment < 2) { if (buf->alignment < 2) {
platform_free((void **) &buf->memory); platform_free((void **) &buf->memory);
} else { } else {
@ -74,15 +75,15 @@ void buffer_init(BufferMemory* buf, byte* data, uint64 size, int32 alignment = 6
buf->alignment = alignment; buf->alignment = alignment;
buf->element_alignment = 0; buf->element_alignment = 0;
DEBUG_MEMORY_INIT((uint64) buf->memory, buf->size); DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size);
DEBUG_MEMORY_RESERVE((uint64) buf->memory, buf->size, 187); DEBUG_MEMORY_RESERVE((uintptr_t) buf->memory, buf->size, 187);
} }
inline inline
void buffer_reset(BufferMemory* buf) void buffer_reset(BufferMemory* buf)
{ {
// @bug aren't we wasting element 0 (see get_memory, we are not using 0 only next element) // @bug aren't we wasting element 0 (see get_memory, we are not using 0 only next element)
DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->head - buf->memory); DEBUG_MEMORY_DELETE((uintptr_t) buf->memory, buf->head - buf->memory);
buf->head = buf->memory; buf->head = buf->memory;
} }
@ -107,7 +108,7 @@ byte* buffer_get_memory(BufferMemory* buf, uint64 size, int32 aligned = 4, bool
memset((void *) buf->head, 0, size); memset((void *) buf->head, 0, size);
} }
DEBUG_MEMORY_WRITE((uint64) buf->head, size); DEBUG_MEMORY_WRITE((uintptr_t) buf->head, size);
byte* offset = buf->head; byte* offset = buf->head;
buf->head += size; buf->head += size;

View File

@ -11,7 +11,6 @@
#include <string.h> #include <string.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
#include "../utils/TestUtils.h" #include "../utils/TestUtils.h"
#include "../utils/EndianUtils.h" #include "../utils/EndianUtils.h"
#include "../utils/BitUtils.h" #include "../utils/BitUtils.h"
@ -58,7 +57,9 @@ void chunk_alloc(ChunkMemory* buf, uint32 count, uint32 chunk_size, int32 alignm
memset(buf->memory, 0, buf->size); memset(buf->memory, 0, buf->size);
DEBUG_MEMORY_INIT((uint64) buf->memory, buf->size); DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size);
LOG_INCREMENT_BY(DEBUG_COUNTER_MEM_ALLOC, buf->size);
LOG_LEVEL_2("Allocated ChunkMemory: %n B", {{LOG_DATA_UINT64, &buf->size}});
} }
inline inline
@ -82,8 +83,8 @@ void chunk_init(ChunkMemory* buf, BufferMemory* data, uint32 count, uint32 chunk
// On another hand we could by accident overwrite the values in free if we are not careful // On another hand we could by accident overwrite the values in free if we are not careful
buf->free = (uint64 *) (buf->memory + count * chunk_size); buf->free = (uint64 *) (buf->memory + count * chunk_size);
DEBUG_MEMORY_INIT((uint64) buf->memory, buf->size); DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size);
DEBUG_MEMORY_RESERVE((uint64) buf->memory, buf->size, 187); DEBUG_MEMORY_RESERVE((uintptr_t) buf->memory, buf->size, 187);
} }
inline inline
@ -108,14 +109,14 @@ void chunk_init(ChunkMemory* buf, byte* data, uint32 count, uint32 chunk_size, i
// On another hand we could by accident overwrite the values in free if we are not careful // On another hand we could by accident overwrite the values in free if we are not careful
buf->free = (uint64 *) (buf->memory + count * chunk_size); buf->free = (uint64 *) (buf->memory + count * chunk_size);
DEBUG_MEMORY_INIT((uint64) buf->memory, buf->size); DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size);
DEBUG_MEMORY_RESERVE((uint64) buf->memory, buf->size, 187); DEBUG_MEMORY_RESERVE((uintptr_t) buf->memory, buf->size, 187);
} }
inline inline
void chunk_free(ChunkMemory* buf) void chunk_free(ChunkMemory* buf)
{ {
DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->size); DEBUG_MEMORY_DELETE((uintptr_t) buf->memory, buf->size);
if (buf->alignment < 2) { if (buf->alignment < 2) {
platform_free((void **) &buf->memory); platform_free((void **) &buf->memory);
} else { } else {
@ -138,7 +139,7 @@ byte* chunk_get_element(ChunkMemory* buf, uint64 element, bool zeroed = false)
memset((void *) offset, 0, buf->chunk_size); memset((void *) offset, 0, buf->chunk_size);
} }
DEBUG_MEMORY_READ((uint64) offset, buf->chunk_size); DEBUG_MEMORY_READ((uintptr_t) offset, buf->chunk_size);
return offset; return offset;
} }
@ -246,7 +247,7 @@ int32 chunk_reserve(ChunkMemory* buf, uint32 elements = 1)
return -1; return -1;
} }
DEBUG_MEMORY_WRITE((uint64) (buf->memory + free_element * buf->chunk_size), elements * buf->chunk_size); DEBUG_MEMORY_WRITE((uintptr_t) (buf->memory + free_element * buf->chunk_size), elements * buf->chunk_size);
buf->last_pos = free_element; buf->last_pos = free_element;
@ -256,14 +257,14 @@ int32 chunk_reserve(ChunkMemory* buf, uint32 elements = 1)
inline inline
void chunk_free_element(ChunkMemory* buf, uint64 free_index, int32 bit_index) void chunk_free_element(ChunkMemory* buf, uint64 free_index, int32 bit_index)
{ {
DEBUG_MEMORY_DELETE((uint64) (buf->memory + (free_index * 64 + bit_index) * buf->chunk_size), buf->chunk_size); DEBUG_MEMORY_DELETE((uintptr_t) (buf->memory + (free_index * 64 + bit_index) * buf->chunk_size), buf->chunk_size);
buf->free[free_index] &= ~(1LL << bit_index); buf->free[free_index] &= ~(1LL << bit_index);
} }
inline inline
void chunk_free_elements(ChunkMemory* buf, uint64 element, uint32 element_count = 1) void chunk_free_elements(ChunkMemory* buf, uint64 element, uint32 element_count = 1)
{ {
DEBUG_MEMORY_DELETE((uint64) (buf->memory + element * buf->chunk_size), buf->chunk_size); DEBUG_MEMORY_DELETE((uintptr_t) (buf->memory + element * buf->chunk_size), buf->chunk_size);
int64 free_index = element / 64; int64 free_index = element / 64;
int32 bit_index = element & 63; int32 bit_index = element & 63;
@ -349,6 +350,8 @@ int64 chunk_load(ChunkMemory* buf, const byte* data)
buf->free = (uint64 *) (buf->memory + buf->count * buf->chunk_size); buf->free = (uint64 *) (buf->memory + buf->count * buf->chunk_size);
LOG_LEVEL_2("Loaded ChunkMemory: %n B", {{LOG_DATA_UINT64, &buf->size}});
return buf->size; return buf->size;
} }

View File

@ -39,12 +39,12 @@ void heap_alloc(Heap* heap, uint32 element_size, uint64 capacity, int32 (*compar
heap->compare = compare; heap->compare = compare;
heap->helper_mem = heap->elements + element_size; heap->helper_mem = heap->elements + element_size;
DEBUG_MEMORY_INIT((uint64) heap->elements, element_size * capacity); DEBUG_MEMORY_INIT((uintptr_t) heap->elements, element_size * capacity);
} }
void heap_free(Heap* heap) void heap_free(Heap* heap)
{ {
DEBUG_MEMORY_DELETE((uint64) heap->elements, heap->element_size * heap->capacity); DEBUG_MEMORY_DELETE((uintptr_t) heap->elements, heap->element_size * heap->capacity);
platform_free((void **) &heap->elements); platform_free((void **) &heap->elements);
} }
@ -61,7 +61,7 @@ void heap_init(Heap* heap, BufferMemory* buf, uint32 element_size, uint64 capaci
heap->size = 0; heap->size = 0;
heap->compare = compare; heap->compare = compare;
DEBUG_MEMORY_INIT((uint64) heap->elements, element_size * capacity); DEBUG_MEMORY_INIT((uintptr_t) heap->elements, element_size * capacity);
} }
void heapify_down(Heap* heap, uint64 index) { void heapify_down(Heap* heap, uint64 index) {
@ -127,7 +127,7 @@ void heap_pop(Heap* heap, void* out) {
return; return;
} }
DEBUG_MEMORY_READ((uint64) heap->elements, heap->element_size); DEBUG_MEMORY_READ((uintptr_t) heap->elements, heap->element_size);
memcpy(out, heap->elements, heap->element_size); memcpy(out, heap->elements, heap->element_size);
void* last_element = heap->elements + ((heap->size - 1) * heap->element_size); void* last_element = heap->elements + ((heap->size - 1) * heap->element_size);
@ -138,7 +138,7 @@ void heap_pop(Heap* heap, void* out) {
inline inline
void* heap_peek(Heap* heap) { void* heap_peek(Heap* heap) {
DEBUG_MEMORY_READ((uint64) heap->elements, heap->element_size); DEBUG_MEMORY_READ((uintptr_t) heap->elements, heap->element_size);
return heap->elements; return heap->elements;
} }

View File

@ -13,7 +13,6 @@
#include <immintrin.h> #include <immintrin.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
#include "../utils/EndianUtils.h" #include "../utils/EndianUtils.h"
#include "../utils/TestUtils.h" #include "../utils/TestUtils.h"
@ -59,7 +58,9 @@ void ring_alloc(RingMemory* ring, uint64 size, uint32 alignment = 64)
memset(ring->memory, 0, ring->size); memset(ring->memory, 0, ring->size);
DEBUG_MEMORY_INIT((uint64) ring->memory, ring->size); DEBUG_MEMORY_INIT((uintptr_t) ring->memory, ring->size);
LOG_INCREMENT_BY(DEBUG_COUNTER_MEM_ALLOC, ring->size);
LOG_LEVEL_2("Allocated RingMemory: %n B", {{LOG_DATA_UINT64, &ring->size}});
} }
inline inline
@ -75,8 +76,8 @@ void ring_init(RingMemory* ring, BufferMemory* buf, uint64 size, uint32 alignmen
ring->size = size; ring->size = size;
ring->alignment = alignment; ring->alignment = alignment;
DEBUG_MEMORY_INIT((uint64) ring->memory, ring->size); DEBUG_MEMORY_INIT((uintptr_t) ring->memory, ring->size);
DEBUG_MEMORY_RESERVE((uint64) ring->memory, ring->size, 187); DEBUG_MEMORY_RESERVE((uintptr_t) ring->memory, ring->size, 187);
} }
inline inline
@ -94,8 +95,8 @@ void ring_init(RingMemory* ring, byte* buf, uint64 size, uint32 alignment = 64)
memset(ring->memory, 0, ring->size); memset(ring->memory, 0, ring->size);
DEBUG_MEMORY_INIT((uint64) ring->memory, ring->size); DEBUG_MEMORY_INIT((uintptr_t) ring->memory, ring->size);
DEBUG_MEMORY_RESERVE((uint64) ring->memory, ring->size, 187); DEBUG_MEMORY_RESERVE((uintptr_t) ring->memory, ring->size, 187);
} }
inline inline
@ -134,7 +135,7 @@ byte* ring_calculate_position(const RingMemory* ring, uint64 size, uint32 aligne
inline inline
void ring_reset(RingMemory* ring) void ring_reset(RingMemory* ring)
{ {
DEBUG_MEMORY_DELETE((uint64) ring->memory, ring->size); DEBUG_MEMORY_DELETE((uintptr_t) ring->memory, ring->size);
ring->head = ring->memory; ring->head = ring->memory;
} }
@ -145,7 +146,7 @@ void ring_move_pointer(RingMemory* ring, byte** pos, uint64 size, uint32 aligned
// Actually, we cannot be sure that this is a read, it could also be a write. // Actually, we cannot be sure that this is a read, it could also be a write.
// However, we better do it once here than manually in every place that uses this function // However, we better do it once here than manually in every place that uses this function
DEBUG_MEMORY_READ((uint64) *pos, size); DEBUG_MEMORY_READ((uintptr_t) *pos, size);
if (aligned > 1) { if (aligned > 1) {
uintptr_t address = (uintptr_t) *pos; uintptr_t address = (uintptr_t) *pos;
@ -188,7 +189,7 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, uint32 aligned = 4, bool ze
memset((void *) ring->head, 0, size); memset((void *) ring->head, 0, size);
} }
DEBUG_MEMORY_WRITE((uint64) ring->head, size); DEBUG_MEMORY_WRITE((uintptr_t) ring->head, size);
byte* offset = ring->head; byte* offset = ring->head;
ring->head += size; ring->head += size;
@ -224,7 +225,7 @@ byte* ring_get_memory_nomove(RingMemory* ring, uint64 size, uint32 aligned = 4,
memset((void *) pos, 0, size); memset((void *) pos, 0, size);
} }
DEBUG_MEMORY_WRITE((uint64) pos, size); DEBUG_MEMORY_WRITE((uintptr_t) pos, size);
return pos; return pos;
} }
@ -236,7 +237,7 @@ byte* ring_get_element(const RingMemory* ring, uint64 element_count, uint64 elem
{ {
int64 index = (element % element_count) - 1; int64 index = (element % element_count) - 1;
DEBUG_MEMORY_READ((uint64) (ring->memory + index * size), 1); DEBUG_MEMORY_READ((uintptr_t) (ring->memory + index * size), 1);
return ring->memory + index * size; return ring->memory + index * size;
} }

View File

@ -9,7 +9,6 @@
#ifndef TOS_MODELS_MOB_C #ifndef TOS_MODELS_MOB_C
#define TOS_MODELS_MOB_C #define TOS_MODELS_MOB_C
#include "../../utils/MathUtils.h"
#include "Mob.h" #include "Mob.h"
#include "MobState.h" #include "MobState.h"

View File

@ -11,7 +11,6 @@
#include "../../../stdlib/Types.h" #include "../../../stdlib/Types.h"
#include "../../../utils/Utils.h" #include "../../../utils/Utils.h"
#include "../../../utils/MathUtils.h"
#include "Drop.h" #include "Drop.h"
// @todo how to do class specific loot table? // @todo how to do class specific loot table?

View File

@ -14,7 +14,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
struct JPSNode { struct JPSNode {
int32 x, y; int32 x, y;

View File

@ -14,7 +14,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
f32 manhattan_2d(v2_f32 a, v2_f32 b) { f32 manhattan_2d(v2_f32 a, v2_f32 b) {
return fabs(a.x - b.x) + fabs(a.y - b.y); return fabs(a.x - b.x) + fabs(a.y - b.y);

View File

@ -14,7 +14,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h"
struct Path { struct Path {

View File

@ -14,7 +14,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../../utils/MathUtils.h"
#include "JpsGrid.h" #include "JpsGrid.h"
#include "../Path.h" #include "../Path.h"

View File

@ -14,7 +14,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../../utils/MathUtils.h"
#include "JpsNode.h" #include "JpsNode.h"

View File

@ -14,7 +14,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../../utils/MathUtils.h"
struct JpsNode { struct JpsNode {
bool is_walkable; bool is_walkable;

View File

@ -15,6 +15,7 @@
#include "../../utils/TestUtils.h" #include "../../utils/TestUtils.h"
// @todo Currently alignment only effects the starting position, but it should also effect the ending/size // @todo Currently alignment only effects the starting position, but it should also effect the ending/size
// @todo Consider to rename file to Allocator.h
inline inline
void* platform_alloc(size_t size) void* platform_alloc(size_t size)
@ -22,10 +23,6 @@ void* platform_alloc(size_t size)
return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
} }
// @question Since we store at least the size of the memory in the beginning,
// does this have a negative impact on caching?
// Our Memory doesn't start at the cache line beginning but at least offset by sizeof(size_t)
inline inline
void* platform_alloc_aligned(size_t size, int32 alignment) void* platform_alloc_aligned(size_t size, int32 alignment)
{ {

View File

@ -276,6 +276,7 @@ int network_info_get(NetworkInfo* info) {
// Get the size of the adapter addresses buffer // Get the size of the adapter addresses buffer
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) { if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) {
// @todo Remove malloc
pAdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(dwSize); pAdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(dwSize);
if (pAdapterAddresses == NULL) { if (pAdapterAddresses == NULL) {
WSACleanup(); WSACleanup();

View File

@ -9,10 +9,27 @@
#ifndef TOS_PLATFORM_WIN32_UTILS_H #ifndef TOS_PLATFORM_WIN32_UTILS_H
#define TOS_PLATFORM_WIN32_UTILS_H #define TOS_PLATFORM_WIN32_UTILS_H
#include "../../stdlib/Types.h"
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#include <string.h> #include <string.h>
#define strtok_r strtok_s #define strtok_r strtok_s
uint32 key_to_unicode(byte scan_code, byte vkey, byte keyboard_state[256])
{
WCHAR char_buffer[5] = {};
int32 result = ToUnicode(vkey, scan_code, keyboard_state, char_buffer, 5, 0);
if (result == 1) {
return (uint32) char_buffer[0];
} else if (result == 2) {
return (uint32) *((uint16 *) char_buffer);
} else if (result == 4) {
return *((uint32 *) char_buffer);
} else {
return 0;
}
}
#endif #endif

View File

@ -28,6 +28,7 @@ struct Window {
// 3. size // 3. size
// 4. fullscreen // 4. fullscreen
byte state_changes; byte state_changes;
// @todo replace bools with states
bool is_focused; bool is_focused;
bool is_fullscreen; bool is_fullscreen;
@ -39,6 +40,7 @@ struct Window {
// The problem is the main program doesn't know which gpuapi we are using, so maybe a void pointer? // The problem is the main program doesn't know which gpuapi we are using, so maybe a void pointer?
HGLRC openGLRC; HGLRC openGLRC;
// @question why do we need the name?
char name[32]; char name[32];
WindowState state_old; WindowState state_old;
}; };

View File

@ -15,7 +15,6 @@
#include "../../../stdlib/Types.h" #include "../../../stdlib/Types.h"
#include "../../../audio/AudioSetting.h" #include "../../../audio/AudioSetting.h"
#include "../../../utils/MathUtils.h"
#include "../../../log/Log.h" #include "../../../log/Log.h"
#include "../../../audio/Audio.cpp" #include "../../../audio/Audio.cpp"
@ -35,7 +34,7 @@ HRESULT WINAPI DirectSoundCreate8Stub(LPCGUID, LPDIRECTSOUND8*, LPUNKNOWN) {
void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_setting) { void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_setting) {
HMODULE lib = LoadLibraryExA((LPCSTR) "dsound.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); HMODULE lib = LoadLibraryExA((LPCSTR) "dsound.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!lib) { if (!lib) {
LOG("DirectSound: Couldn't load dsound.dll\n", true, true); LOG(true, "DirectSound: Couldn't load dsound.dll\n");
return; return;
} }
@ -43,13 +42,13 @@ void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_settin
DirectSoundCreate8_t* DirectSoundCreate8 = (DirectSoundCreate8_t *) GetProcAddress(lib, "DirectSoundCreate8"); DirectSoundCreate8_t* DirectSoundCreate8 = (DirectSoundCreate8_t *) GetProcAddress(lib, "DirectSoundCreate8");
if (!DirectSoundCreate8 || !SUCCEEDED(DirectSoundCreate8(0, &api_setting->audio_handle, 0))) { if (!DirectSoundCreate8 || !SUCCEEDED(DirectSoundCreate8(0, &api_setting->audio_handle, 0))) {
LOG("DirectSound: DirectSoundCreate8 failed\n", true, true); LOG(true, "DirectSound: DirectSoundCreate8 failed\n");
return; return;
} }
if(!SUCCEEDED(api_setting->audio_handle->SetCooperativeLevel(hwnd, DSSCL_PRIORITY))) { if(!SUCCEEDED(api_setting->audio_handle->SetCooperativeLevel(hwnd, DSSCL_PRIORITY))) {
LOG("DirectSound: SetCooperativeLevel failed.\n", true, true); LOG(true, "DirectSound: SetCooperativeLevel failed.\n");
return; return;
} }
@ -71,13 +70,13 @@ void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_settin
buffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER; buffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
if(!SUCCEEDED(api_setting->audio_handle->CreateSoundBuffer(&buffer_desc, &api_setting->primary_buffer, 0))) { if(!SUCCEEDED(api_setting->audio_handle->CreateSoundBuffer(&buffer_desc, &api_setting->primary_buffer, 0))) {
LOG("DirectSound: CreateSoundBuffer1 failed.\n", true, true); LOG(true, "DirectSound: CreateSoundBuffer1 failed.\n");
return; return;
} }
if (!SUCCEEDED(api_setting->primary_buffer->SetFormat(&wf))) { if (!SUCCEEDED(api_setting->primary_buffer->SetFormat(&wf))) {
LOG("DirectSound: SetFormat failed.\n", true, true); LOG(true, "DirectSound: SetFormat failed.\n");
return; return;
} }
@ -93,7 +92,7 @@ void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_settin
buffer_desc2.lpwfxFormat = &wf; buffer_desc2.lpwfxFormat = &wf;
if(!SUCCEEDED(api_setting->audio_handle->CreateSoundBuffer(&buffer_desc2, &api_setting->secondary_buffer, 0))) { if(!SUCCEEDED(api_setting->audio_handle->CreateSoundBuffer(&buffer_desc2, &api_setting->secondary_buffer, 0))) {
LOG("DirectSound: CreateSoundBuffer2 failed.\n", true, true); LOG(true, "DirectSound: CreateSoundBuffer2 failed.\n");
return; return;
} }
@ -143,7 +142,7 @@ uint32 audio_buffer_fillable(const AudioSetting* setting, const DirectSoundSetti
DWORD player_cursor; DWORD player_cursor;
DWORD write_cursor; DWORD write_cursor;
if (!SUCCEEDED(api_setting->secondary_buffer->GetCurrentPosition(&player_cursor, &write_cursor))) { if (!SUCCEEDED(api_setting->secondary_buffer->GetCurrentPosition(&player_cursor, &write_cursor))) {
LOG("DirectSound: GetCurrentPosition failed.\n", true, true); LOG(true, "DirectSound: GetCurrentPosition failed.\n");
return 0; return 0;
} }

View File

@ -18,7 +18,6 @@
#include "../../../stdlib/Types.h" #include "../../../stdlib/Types.h"
#include "../../../audio/AudioSetting.h" #include "../../../audio/AudioSetting.h"
#include "../../../utils/MathUtils.h"
#include "../../../log/Log.h" #include "../../../log/Log.h"
#include "../../../audio/Audio.cpp" #include "../../../audio/Audio.cpp"
@ -44,7 +43,7 @@ typedef HRESULT WINAPI IAudioClient_GetService_t(IAudioClient*, REFIID, void**);
void audio_load(HWND hwnd, AudioSetting* setting, WasapiSetting* api_setting) { void audio_load(HWND hwnd, AudioSetting* setting, WasapiSetting* api_setting) {
HMODULE ole32 = LoadLibraryExA((LPCSTR) "ole32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); HMODULE ole32 = LoadLibraryExA((LPCSTR) "ole32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!ole32) { if (!ole32) {
LOG("Wasapi: Couldn't load ole32.dll\n", true, true); LOG(true, "Wasapi: Couldn't load ole32.dll\n");
return; return;
} }
@ -53,14 +52,14 @@ void audio_load(HWND hwnd, AudioSetting* setting, WasapiSetting* api_setting) {
CoCreateInstance_t* co_create_instance = (CoCreateInstance_t *) GetProcAddress(ole32, "CoCreateInstance"); CoCreateInstance_t* co_create_instance = (CoCreateInstance_t *) GetProcAddress(ole32, "CoCreateInstance");
if (!co_initialize_ex || !co_create_instance) { if (!co_initialize_ex || !co_create_instance) {
LOG("Wasapi: ole32 function binding failed\n", true, true); LOG(true, "Wasapi: ole32 function binding failed\n");
return; return;
} }
HMODULE mmdevapi = LoadLibraryExA((LPCSTR) "mmdevapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); HMODULE mmdevapi = LoadLibraryExA((LPCSTR) "mmdevapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!mmdevapi) { if (!mmdevapi) {
LOG("Wasapi: Couldn't load mmdevapi.dll\n", true, true); LOG(true, "Wasapi: Couldn't load mmdevapi.dll\n");
return; return;
} }
@ -69,14 +68,14 @@ void audio_load(HWND hwnd, AudioSetting* setting, WasapiSetting* api_setting) {
IMMDevice_Activate_t* IMMDevice_Activate = (IMMDevice_Activate_t *) GetProcAddress(mmdevapi, "IMMDevice_Activate"); IMMDevice_Activate_t* IMMDevice_Activate = (IMMDevice_Activate_t *) GetProcAddress(mmdevapi, "IMMDevice_Activate");
if (!IMMDeviceEnumerator_GetDefaultAudioEndpoint || !IMMDevice_Activate) { if (!IMMDeviceEnumerator_GetDefaultAudioEndpoint || !IMMDevice_Activate) {
LOG("Wasapi: mmdevapi function binding failed\n", true, true); LOG(true, "Wasapi: mmdevapi function binding failed\n");
return; return;
} }
HMODULE audioclient = LoadLibraryExA((LPCSTR) "audioclient.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); HMODULE audioclient = LoadLibraryExA((LPCSTR) "audioclient.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!audioclient) { if (!audioclient) {
LOG("Wasapi: Couldn't load audioclient.dll\n", true, true); LOG(true, "Wasapi: Couldn't load audioclient.dll\n");
return; return;
} }
@ -88,14 +87,14 @@ void audio_load(HWND hwnd, AudioSetting* setting, WasapiSetting* api_setting) {
IAudioClient_GetService_t* pIAudioClient_GetService = (IAudioClient_GetService_t *) GetProcAddress(audioclient, "IAudioClient_GetService"); IAudioClient_GetService_t* pIAudioClient_GetService = (IAudioClient_GetService_t *) GetProcAddress(audioclient, "IAudioClient_GetService");
if (!pIAudioClient_GetMixFormat || !pIAudioClient_Initialize || !pIAudioClient_Start || !pIAudioClient_Stop || !pIAudioClient_GetService) { if (!pIAudioClient_GetMixFormat || !pIAudioClient_Initialize || !pIAudioClient_Start || !pIAudioClient_Stop || !pIAudioClient_GetService) {
LOG("Wasapi: audioclient function binding failed\n", true, true); LOG(true, "Wasapi: audioclient function binding failed\n");
return; return;
} }
HRESULT hr = co_initialize_ex(NULL, COINIT_MULTITHREADED); HRESULT hr = co_initialize_ex(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) { if (FAILED(hr)) {
LOG("Wasapi: Wasapi initialize failed\n", true, true); LOG(true, "Wasapi: Wasapi initialize failed\n");
return; return;
} }
@ -105,14 +104,14 @@ void audio_load(HWND hwnd, AudioSetting* setting, WasapiSetting* api_setting) {
hr = co_create_instance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **) &enumerator); hr = co_create_instance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **) &enumerator);
if (FAILED(hr)) { if (FAILED(hr)) {
LOG("Wasapi: Wasapi CreateInstance failed\n", true, true); LOG(true, "Wasapi: Wasapi CreateInstance failed\n");
return; return;
} }
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eConsole, &device); hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eConsole, &device);
if (FAILED(hr)) { if (FAILED(hr)) {
LOG("Wasapi: Wasapi DefaultAudioEndpoint failed\n", true, true); LOG(true, "Wasapi: Wasapi DefaultAudioEndpoint failed\n");
enumerator->Release(); enumerator->Release();
@ -121,7 +120,7 @@ void audio_load(HWND hwnd, AudioSetting* setting, WasapiSetting* api_setting) {
hr = IMMDevice_Activate(device, IID_IAudioClient, CLSCTX_ALL, NULL, (void **) &api_setting->audio_handle); hr = IMMDevice_Activate(device, IID_IAudioClient, CLSCTX_ALL, NULL, (void **) &api_setting->audio_handle);
if (FAILED(hr)) { if (FAILED(hr)) {
LOG("Wasapi: Wasapi DeviceActivate failed\n", true, true); LOG(true, "Wasapi: Wasapi DeviceActivate failed\n");
device->Release(); device->Release();
enumerator->Release(); enumerator->Release();

View File

@ -37,20 +37,20 @@ void audio_load(HWND hwnd, AudioSetting* setting, XAudio2Setting* api_setting) {
CoInitialize(NULL); CoInitialize(NULL);
HMODULE lib = LoadLibraryExA((LPCSTR) "xaudio2_9.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); HMODULE lib = LoadLibraryExA((LPCSTR) "xaudio2_9.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!lib) { if (!lib) {
LOG("Xaudio2: Couldn't load xaudio2_9.dll\n", true, true); LOG(true, "Xaudio2: Couldn't load xaudio2_9.dll\n");
lib = LoadLibraryExA((LPCSTR) "xaudio2_8.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); lib = LoadLibraryExA((LPCSTR) "xaudio2_8.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
} }
if (!lib) { if (!lib) {
LOG("Xaudio2: Couldn't load xaudio2_8.dll\n", true, true); LOG(true, "Xaudio2: Couldn't load xaudio2_8.dll\n");
return; return;
} }
XAudio2Create_t* XAudio2Create = (XAudio2Create_t *) GetProcAddress(lib, "XAudio2Create"); XAudio2Create_t* XAudio2Create = (XAudio2Create_t *) GetProcAddress(lib, "XAudio2Create");
if (!XAudio2Create || !SUCCEEDED(XAudio2Create(&api_setting->audio_handle, 0, XAUDIO2_DEFAULT_PROCESSOR))) { if (!XAudio2Create || !SUCCEEDED(XAudio2Create(&api_setting->audio_handle, 0, XAUDIO2_DEFAULT_PROCESSOR))) {
LOG("Xaudio2: XAudio2Create failed\n", true, true); LOG(true, "Xaudio2: XAudio2Create failed\n");
return; return;
} }
@ -63,7 +63,7 @@ void audio_load(HWND hwnd, AudioSetting* setting, XAudio2Setting* api_setting) {
0, 0,
NULL)) NULL))
) { ) {
LOG("Xaudio2: CreateMasteringVoice failed\n", true, true); LOG(true, "Xaudio2: CreateMasteringVoice failed\n");
return; return;
} }
@ -78,7 +78,7 @@ void audio_load(HWND hwnd, AudioSetting* setting, XAudio2Setting* api_setting) {
wf.cbSize = 0; wf.cbSize = 0;
if (!SUCCEEDED(api_setting->audio_handle->CreateSourceVoice(&api_setting->source_voice, &wf))) { if (!SUCCEEDED(api_setting->audio_handle->CreateSourceVoice(&api_setting->source_voice, &wf))) {
LOG("Xaudio2: CreateSourceVoice failed\n", true, true); LOG(true, "Xaudio2: CreateSourceVoice failed\n");
return; return;
} }
@ -187,7 +187,7 @@ void audio_play_buffer(AudioSetting* setting, XAudio2Setting* api_setting) {
); );
if (!SUCCEEDED(api_setting->source_voice->SubmitSourceBuffer(&api_setting->internal_buffer[idx]))) { if (!SUCCEEDED(api_setting->source_voice->SubmitSourceBuffer(&api_setting->internal_buffer[idx]))) {
LOG("Xaudio2: SubmitSourceBuffer failed\n", true, true); LOG(true, "Xaudio2: SubmitSourceBuffer failed\n");
return; return;
} }

View File

@ -155,7 +155,7 @@ uint32 hid_device_poll(Input* state, uint64 time) {
} }
input_set_controller_state(state, &controller, time); input_set_controller_state(state, &controller, time);
state->state_change_button = true; state->general_states |= INPUT_STATE_GENERAL_BUTTON_CHANGE;
state->time_last_input_check = time; state->time_last_input_check = time;
return 0; return 0;

View File

@ -226,44 +226,44 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32
InputKey key; InputKey key;
if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) { if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) {
key.key_state = KEY_STATE_PRESSED; key.key_state = KEY_PRESS_TYPE_PRESSED;
key.key_id = INPUT_MOUSE_BUTTON_1; key.scan_code = INPUT_MOUSE_BUTTON_1;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) {
key.key_state = KEY_STATE_RELEASED; key.key_state = KEY_PRESS_TYPE_RELEASED;
key.key_id = INPUT_MOUSE_BUTTON_1; key.scan_code = INPUT_MOUSE_BUTTON_1;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) {
key.key_state = KEY_STATE_PRESSED; key.key_state = KEY_PRESS_TYPE_PRESSED;
key.key_id = INPUT_MOUSE_BUTTON_2; key.scan_code = INPUT_MOUSE_BUTTON_2;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) {
key.key_state = KEY_STATE_RELEASED; key.key_state = KEY_PRESS_TYPE_RELEASED;
key.key_id = INPUT_MOUSE_BUTTON_2; key.scan_code = INPUT_MOUSE_BUTTON_2;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) {
key.key_state = KEY_STATE_PRESSED; key.key_state = KEY_PRESS_TYPE_PRESSED;
key.key_id = INPUT_MOUSE_BUTTON_3; key.scan_code = INPUT_MOUSE_BUTTON_3;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) {
key.key_state = KEY_STATE_RELEASED; key.key_state = KEY_PRESS_TYPE_RELEASED;
key.key_id = INPUT_MOUSE_BUTTON_3; key.scan_code = INPUT_MOUSE_BUTTON_3;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) {
key.key_state = KEY_STATE_PRESSED; key.key_state = KEY_PRESS_TYPE_PRESSED;
key.key_id = INPUT_MOUSE_BUTTON_4; key.scan_code = INPUT_MOUSE_BUTTON_4;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) {
key.key_state = KEY_STATE_RELEASED; key.key_state = KEY_PRESS_TYPE_RELEASED;
key.key_id = INPUT_MOUSE_BUTTON_4; key.scan_code = INPUT_MOUSE_BUTTON_4;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) {
key.key_state = KEY_STATE_PRESSED; key.key_state = KEY_PRESS_TYPE_PRESSED;
key.key_id = INPUT_MOUSE_BUTTON_5; key.scan_code = INPUT_MOUSE_BUTTON_5;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) {
key.key_state = KEY_STATE_RELEASED; key.key_state = KEY_PRESS_TYPE_RELEASED;
key.key_id = INPUT_MOUSE_BUTTON_5; key.scan_code = INPUT_MOUSE_BUTTON_5;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
// @bug not working // @bug not working
key.key_state = KEY_STATE_RELEASED; key.key_state = KEY_PRESS_TYPE_RELEASED;
key.key_id = INPUT_MOUSE_BUTTON_WHEEL; key.scan_code = INPUT_MOUSE_BUTTON_WHEEL;
key.value = (int16) raw->data.mouse.usButtonData; key.value = (int16) raw->data.mouse.usButtonData;
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_HWHEEL) { } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_HWHEEL) {
// @bug not working // @bug not working
key.key_state = KEY_STATE_RELEASED; key.key_state = KEY_PRESS_TYPE_RELEASED;
key.key_id = INPUT_MOUSE_BUTTON_HWHEEL; key.scan_code = INPUT_MOUSE_BUTTON_HWHEEL;
key.value = (int16) raw->data.mouse.usButtonData; key.value = (int16) raw->data.mouse.usButtonData;
} else { } else {
return 0; return 0;
@ -271,12 +271,12 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32
++input_count; ++input_count;
key.key_id |= INPUT_MOUSE_PREFIX; key.scan_code |= INPUT_MOUSE_PREFIX;
key.time = time; key.time = time;
input_set_state(states[i].state.state_keys, &key); input_set_state(states[i].state.active_keys, &key);
states[i].state_change_button = true; states[i].general_states |= INPUT_STATE_GENERAL_BUTTON_CHANGE;
} else if (states[i].mouse_movement) { } else if (states[i].general_states & INPUT_STATE_GENERAL_MOUSE_MOVEMENT) {
// @question do we want to handle mouse movement for every individual movement, or do we want to pull it // @question do we want to handle mouse movement for every individual movement, or do we want to pull it
if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
RECT rect; RECT rect;
@ -301,7 +301,7 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32
states[i].state.x = MulDiv(raw->data.mouse.lLastX, rect.right, 65535) + rect.left; states[i].state.x = MulDiv(raw->data.mouse.lLastX, rect.right, 65535) + rect.left;
states[i].state.y = MulDiv(raw->data.mouse.lLastY, rect.bottom, 65535) + rect.top; states[i].state.y = MulDiv(raw->data.mouse.lLastY, rect.bottom, 65535) + rect.top;
states[i].state_change_mouse = true; states[i].general_states |= INPUT_STATE_GENERAL_MOUSE_CHANGE;
} else if (raw->data.mouse.lLastX != 0 || raw->data.mouse.lLastY != 0) { } else if (raw->data.mouse.lLastX != 0 || raw->data.mouse.lLastY != 0) {
states[i].state.dx += raw->data.mouse.lLastX; states[i].state.dx += raw->data.mouse.lLastX;
states[i].state.dy += raw->data.mouse.lLastY; states[i].state.dy += raw->data.mouse.lLastY;
@ -309,7 +309,7 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32
states[i].state.x = states[i].state.x + raw->data.mouse.lLastX; states[i].state.x = states[i].state.x + raw->data.mouse.lLastX;
states[i].state.y = states[i].state.y + raw->data.mouse.lLastY; states[i].state.y = states[i].state.y + raw->data.mouse.lLastY;
states[i].state_change_mouse = true; states[i].general_states |= INPUT_STATE_GENERAL_MOUSE_CHANGE;
} }
} }
} else if (raw->header.dwType == RIM_TYPEKEYBOARD) { } else if (raw->header.dwType == RIM_TYPEKEYBOARD) {
@ -324,21 +324,26 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32
return 0; return 0;
} }
uint16 new_state; KeyPressType new_state;
if (raw->data.keyboard.Flags == RI_KEY_BREAK) { if (raw->data.keyboard.Flags == RI_KEY_BREAK) {
new_state = KEY_STATE_RELEASED; new_state = KEY_PRESS_TYPE_RELEASED;
} else if (raw->data.keyboard.Flags == RI_KEY_MAKE) { } else if (raw->data.keyboard.Flags == RI_KEY_MAKE) {
new_state = KEY_STATE_PRESSED; new_state = KEY_PRESS_TYPE_PRESSED;
} else { } else {
return 0; return 0;
} }
++input_count; ++input_count;
// @todo change to MakeCode instead of VKey // @todo we need to support vkey and MakeCode/ScanCode for input mode -> typing and recognizing the respective unicode
InputKey key = {(uint16) (raw->data.keyboard.VKey | INPUT_KEYBOARD_PREFIX), new_state, 0, time}; InputKey key = {
input_set_state(states[i].state.state_keys, &key); (uint16) (raw->data.keyboard.MakeCode | INPUT_KEYBOARD_PREFIX),
states[i].state_change_button = true; (uint16) (raw->data.keyboard.VKey | INPUT_KEYBOARD_PREFIX),
new_state, time, 0, false
};
input_set_state(states[i].state.active_keys, &key);
states[i].general_states |= INPUT_STATE_GENERAL_BUTTON_CHANGE;
} else if (raw->header.dwType == RIM_TYPEHID } else if (raw->header.dwType == RIM_TYPEHID
&& raw->header.dwSize > sizeof(RAWINPUT) && raw->header.dwSize > sizeof(RAWINPUT)
) { ) {
@ -369,7 +374,7 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32
} }
input_set_controller_state(&states[i], &controller, time); input_set_controller_state(&states[i], &controller, time);
states[i].state_change_button = true; states[i].general_states |= INPUT_STATE_GENERAL_BUTTON_CHANGE;
states[i].time_last_input_check = time; states[i].time_last_input_check = time;
} }

View File

@ -14,7 +14,6 @@
#include "../../../input/ControllerInput.h" #include "../../../input/ControllerInput.h"
#include "../../../stdlib/Types.h" #include "../../../stdlib/Types.h"
#include "../../../utils/MathUtils.h"
// @todo consider to remove some global_persist and defines since we are never calling it somewhere else // @todo consider to remove some global_persist and defines since we are never calling it somewhere else

View File

@ -14,7 +14,6 @@
#include "../../../../input/ControllerInput.h" #include "../../../../input/ControllerInput.h"
#include "../../../../input/InputConnectionType.h" #include "../../../../input/InputConnectionType.h"
#include "../../../../utils/BitUtils.h" #include "../../../../utils/BitUtils.h"
#include "../../../../utils/MathUtils.h"
// @bug bluetooth and USB have different formats?! // @bug bluetooth and USB have different formats?!
// https://github.com/nondebug/dualsense // https://github.com/nondebug/dualsense

View File

@ -14,7 +14,6 @@
#include "../../../../input/ControllerInput.h" #include "../../../../input/ControllerInput.h"
#include "../../../../input/InputConnectionType.h" #include "../../../../input/InputConnectionType.h"
#include "../../../../utils/BitUtils.h" #include "../../../../utils/BitUtils.h"
#include "../../../../utils/MathUtils.h"
inline inline
void input_map_dualshock4(ControllerInput* controller, InputConnectionType connection_type, byte* data) void input_map_dualshock4(ControllerInput* controller, InputConnectionType connection_type, byte* data)

View File

@ -351,7 +351,7 @@ void atomic_and_relaxed(volatile uint64* value, uint64 mask)
inline inline
void atomic_and_relaxed(volatile int64* value, int64 mask) void atomic_and_relaxed(volatile int64* value, int64 mask)
{ {
InterlockedAnd64NoFence((volatile LONG64 *) value, mask); InterlockedAnd64NoFence((volatile LONG64 *) value, (LONG64) mask);
} }
inline inline
@ -456,7 +456,7 @@ int32 atomic_get_acquire(volatile int32* value)
inline inline
int64 atomic_get_acquire(volatile int64* value) int64 atomic_get_acquire(volatile int64* value)
{ {
return (int64) InterlockedCompareExchangeAcquire((long *) value, 0, 0); return (int64) InterlockedCompareExchangeAcquire64((LONG64 *) value, 0, 0);
} }
inline inline
@ -492,13 +492,13 @@ void atomic_decrement_acquire(volatile int32* value)
inline inline
void atomic_increment_acquire(volatile int64* value) void atomic_increment_acquire(volatile int64* value)
{ {
InterlockedIncrementAcquire((long *) value); InterlockedIncrementAcquire64((LONG64 *) value);
} }
inline inline
void atomic_decrement_acquire(volatile int64* value) void atomic_decrement_acquire(volatile int64* value)
{ {
InterlockedDecrementAcquire((long *) value); InterlockedDecrementAcquire64((LONG64 *) value);
} }
inline inline
@ -516,13 +516,13 @@ void atomic_sub_acquire(volatile int32* value, int32 decrement)
inline inline
void atomic_add_acquire(volatile int64* value, int64 increment) void atomic_add_acquire(volatile int64* value, int64 increment)
{ {
InterlockedAddAcquire((long *) value, (long) increment); InterlockedAddAcquire64((LONG64 *) value, (LONG64) increment);
} }
inline inline
void atomic_sub_acquire(volatile int64* value, int64 decrement) void atomic_sub_acquire(volatile int64* value, int64 decrement)
{ {
InterlockedAddAcquire((long *) value, -1 * ((long) decrement)); InterlockedAddAcquire64((LONG64 *) value, -1 * ((LONG64) decrement));
} }
inline inline
@ -819,7 +819,7 @@ int32 atomic_get_release(volatile int32* value)
inline inline
int64 atomic_get_release(volatile int64* value) int64 atomic_get_release(volatile int64* value)
{ {
return (int64) InterlockedCompareExchangeRelease((long *) value, 0, 0); return (int64) InterlockedCompareExchangeRelease64((LONG64 *) value, 0, 0);
} }
inline inline
@ -1314,7 +1314,7 @@ void atomic_set_acquire_release(volatile uint32* value, uint32 new_value)
inline inline
void atomic_set_acquire_release(volatile uint64* value, uint64 new_value) void atomic_set_acquire_release(volatile uint64* value, uint64 new_value)
{ {
InterlockedExchange((long *) value, (long) new_value); InterlockedExchange64((LONG64 *) value, (LONG64) new_value);
} }
inline inline

View File

@ -140,6 +140,8 @@ void hashmap_create(HashMap* hm, int32 count, int32 element_size, RingMemory* ri
hm->table = (void **) data; hm->table = (void **) data;
chunk_init(&hm->buf, data + sizeof(void *) * count, count, element_size, 8); chunk_init(&hm->buf, data + sizeof(void *) * count, count, element_size, 8);
LOG_LEVEL_2("Created HashMap for %n elements with %n B per element = %n B", {{LOG_DATA_INT32, &count}, {LOG_DATA_INT32, &element_size}, {LOG_DATA_UINT64, &hm->buf.size}});
} }
// WARNING: element_size = element size + remaining HashEntry data size // WARNING: element_size = element size + remaining HashEntry data size
@ -153,6 +155,8 @@ void hashmap_create(HashMap* hm, int32 count, int32 element_size, BufferMemory*
hm->table = (void **) data; hm->table = (void **) data;
chunk_init(&hm->buf, data + sizeof(void *) * count, count, element_size, 8); chunk_init(&hm->buf, data + sizeof(void *) * count, count, element_size, 8);
LOG_LEVEL_2("Created HashMap for %n elements with %n B per element = %n B", {{LOG_DATA_INT32, &count}, {LOG_DATA_INT32, &element_size}, {LOG_DATA_UINT64, &hm->buf.size}});
} }
// WARNING: element_size = element size + remaining HashEntry data size // WARNING: element_size = element size + remaining HashEntry data size
@ -160,6 +164,8 @@ void hashmap_create(HashMap* hm, int32 count, int32 element_size, byte* buf)
{ {
hm->table = (void **) buf; hm->table = (void **) buf;
chunk_init(&hm->buf, buf + sizeof(void *) * count, count, element_size, 8); chunk_init(&hm->buf, buf + sizeof(void *) * count, count, element_size, 8);
LOG_LEVEL_2("Created HashMap for %n elements with %n B per element = %n B", {{LOG_DATA_INT32, &count}, {LOG_DATA_INT32, &element_size}, {LOG_DATA_UINT64, &hm->buf.size}});
} }
// Calculates how large a hashmap will be // Calculates how large a hashmap will be
@ -399,7 +405,7 @@ HashEntry* hashmap_get_reserve(HashMap* hm, const char* key)
while (entry != NULL) { while (entry != NULL) {
if (str_compare(entry->key, key, HASH_MAP_MAX_KEY_LENGTH) == 0) { if (str_compare(entry->key, key, HASH_MAP_MAX_KEY_LENGTH) == 0) {
DEBUG_MEMORY_READ((uint64) entry, sizeof(HashEntry)); DEBUG_MEMORY_READ((uintptr_t) entry, sizeof(HashEntry));
return entry; return entry;
} }
@ -434,7 +440,7 @@ HashEntry* hashmap_get_entry(const HashMap* hm, const char* key) {
while (entry != NULL) { while (entry != NULL) {
if (str_compare(entry->key, key, HASH_MAP_MAX_KEY_LENGTH) == 0) { if (str_compare(entry->key, key, HASH_MAP_MAX_KEY_LENGTH) == 0) {
DEBUG_MEMORY_READ((uint64) entry, sizeof(HashEntry)); DEBUG_MEMORY_READ((uintptr_t) entry, sizeof(HashEntry));
return entry; return entry;
} }
@ -452,7 +458,7 @@ HashEntry* hashmap_get_entry(const HashMap* hm, const char* key, uint64 hash) {
while (entry != NULL) { while (entry != NULL) {
if (str_compare(entry->key, key, HASH_MAP_MAX_KEY_LENGTH) == 0) { if (str_compare(entry->key, key, HASH_MAP_MAX_KEY_LENGTH) == 0) {
DEBUG_MEMORY_READ((uint64) entry, sizeof(HashEntry)); DEBUG_MEMORY_READ((uintptr_t) entry, sizeof(HashEntry));
return entry; return entry;
} }
@ -664,7 +670,7 @@ HashEntryKeyInt32* hashmap_get_entry(const HashMap* hm, int32 key) {
while (entry != NULL) { while (entry != NULL) {
if (entry->key == key) { if (entry->key == key) {
DEBUG_MEMORY_READ((uint64) entry, sizeof(HashEntryKeyInt32)); DEBUG_MEMORY_READ((uintptr_t) entry, sizeof(HashEntryKeyInt32));
return entry; return entry;
} }
@ -682,7 +688,7 @@ HashEntryKeyInt32* hashmap_get_entry(const HashMap* hm, int32 key, uint64 hash)
while (entry != NULL) { while (entry != NULL) {
if (entry->key == key) { if (entry->key == key) {
DEBUG_MEMORY_READ((uint64) entry, sizeof(HashEntryKeyInt32)); DEBUG_MEMORY_READ((uintptr_t) entry, sizeof(HashEntryKeyInt32));
return entry; return entry;
} }
@ -851,6 +857,8 @@ int64 hashmap_load(HashMap* hm, const byte* data)
} }
chunk_iterate_end; chunk_iterate_end;
LOG_LEVEL_2("Loaded HashMap: %n B", {{LOG_DATA_UINT64, &hm->buf.size}});
// How many bytes was read from data // How many bytes was read from data
return sizeof(hm->buf.count) // hash map count = buffer count return sizeof(hm->buf.count) // hash map count = buffer count
+ hm->buf.count * sizeof(uint64) // table content + hm->buf.count * sizeof(uint64) // table content

View File

@ -54,6 +54,42 @@ typedef char sbyte;
typedef uintptr_t umm; typedef uintptr_t umm;
typedef intptr_t smm; typedef intptr_t smm;
#define OMS_PI 3.14159265358979323846f
#define OMS_PI_OVER_TWO (OMS_PI / 2.0f)
#define OMS_PI_OVER_FOUR (OMS_PI / 4.0f)
#define OMS_TWO_PI (2.0f * OMS_PI)
#define OMS_MAX(a, b) ((a) > (b) ? (a) : (b))
#define OMS_MIN(a, b) ((a) > (b) ? (b) : (a))
// @todo Switch the order of high and low
#define OMS_CLAMP(val, high, low) ((val) < (low) ? (low) : ((val) > (high) ? (high) : (val)))
#define OMS_ABS(a) ((a) > 0 ? (a) : -(a))
#define OMS_ABS_INT8(a) ((a) & 0x7F)
#define OMS_ABS_INT16(a) ((a) & 0x7FFF)
#define OMS_ABS_INT32(a) ((a) & 0x7FFFFFFF)
#define OMS_ABS_INT64(a) ((a) & 0x7FFFFFFFFFFFFFFF)
#define OMS_ABS_F32(a) ((f32) (((int32) (a)) & 0x7FFFFFFF))
#define OMS_ABS_F64(a) ((f64) (((int64) (a)) & 0x7FFFFFFFFFFFFFFF))
#define OMS_DEG2RAD(angle) ((angle) * OMS_PI / 180.0f)
#define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI)
#define ROUND_TO_NEAREST(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
#define OMS_ROUND_POSITIVE(x) ((int32)((x) + 0.5f))
#define OMS_ROUND(x) (((x) >= 0) ? ((int32)((x) + 0.5f)) : ((int32)((x) - 0.5f)))
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
#define OMS_CEIL(x) ((x) == (int32)(x) ? (int32)(x) : ((x) > 0 ? (int32)(x) + 1 : (int32)(x)))
#define FLOAT_CAST_EPS 0.001953125
// Modulo function when b is a power of 2
#define MODULO_2(a, b) ((a) & (b - 1))
#define SQRT_2 1.4142135623730950488016887242097f
#define KILOBYTE 1024 #define KILOBYTE 1024
#define MEGABYTE 1048576 #define MEGABYTE 1048576
#define GIGABYTE 1073741824 #define GIGABYTE 1073741824
@ -203,6 +239,10 @@ struct v2_f32 {
f32 x, y; f32 x, y;
}; };
struct {
f32 width, height;
};
f32 v[2]; f32 v[2];
}; };
}; };

View File

@ -26,6 +26,7 @@
void thread_create(Worker* worker, ThreadJobFunc routine, void* arg) void thread_create(Worker* worker, ThreadJobFunc routine, void* arg)
{ {
LOG_LEVEL_2("Thread started", {});
pthread_create(&worker->thread, NULL, routine, arg); pthread_create(&worker->thread, NULL, routine, arg);
} }
@ -33,6 +34,7 @@ void thread_stop(Worker* worker)
{ {
atomic_set_acquire(&worker->state, 0); atomic_set_acquire(&worker->state, 0);
pthread_join(worker->thread, NULL); pthread_join(worker->thread, NULL);
LOG_LEVEL_2("Thread ended", {});
} }
#endif #endif

View File

@ -63,9 +63,12 @@ static THREAD_RETURN thread_pool_worker(void* arg)
atomic_increment_relaxed(&pool->working_cnt); atomic_increment_relaxed(&pool->working_cnt);
atomic_set_release(&work->state, 2); atomic_set_release(&work->state, 2);
LOG_LEVEL_2("ThreadPool worker started", {});
work->func(work); work->func(work);
LOG_LEVEL_2("ThreadPool worker ended", {});
// At the end of a thread the ring memory automatically is considered freed // At the end of a thread the ring memory automatically is considered freed
DEBUG_MEMORY_FREE((uint64) work->ring.memory, work->ring.size); DEBUG_MEMORY_FREE((uintptr_t) work->ring.memory, work->ring.size);
LOG_LEVEL_2("Freed thread RingMemory: %n B", {{LOG_DATA_UINT64, &work->ring.size}});
atomic_set_release(&work->state, 1); atomic_set_release(&work->state, 1);
// Job gets marked after completion -> can be overwritten now // Job gets marked after completion -> can be overwritten now

View File

@ -1,38 +0,0 @@
/**
* Jingga
*
* @package Utils
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_UTILS_MATH_UTILS_H
#define TOS_UTILS_MATH_UTILS_H
#include <math.h>
#define OMS_PI 3.14159265358979323846f
#define OMS_PI_OVER_TWO (OMS_PI / 2.0f)
#define OMS_PI_OVER_FOUR (OMS_PI / 4.0f)
#define OMS_TWO_PI (2.0f * OMS_PI)
#define OMS_MAX(a, b) ((a) > (b) ? (a) : (b))
#define OMS_MIN(a, b) ((a) > (b) ? (b) : (a))
#define OMS_CLAMP(val, high, low) (OMS_MAX(OMS_MIN((val), (high)), (low)))
#define OMS_ABS(a) ((a) > 0 ? (a) : -(a))
#define OMS_DEG2RAD(angle) ((angle) * OMS_PI / 180.0f)
#define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI)
#define ROUND_TO_NEAREST(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
#define OMS_CEIL(x) ((x) == (int)(x) ? (int)(x) : ((x) > 0 ? (int)(x) + 1 : (int)(x)))
#define OMS_ROUND(x) (((x) >= 0) ? ((int)((x) + 0.5f)) : ((int)((x) - 0.5f)))
#define OMS_ROUND_POSITIVE(x) ((int)((x) + 0.5f))
#define FLOAT_CAST_EPS 0.001953125
// Modulo function when b is a power of 2
#define MODULO_2(a, b) ((a) & (b - 1))
#define SQRT_2 1.4142135623730950488016887242097f
#endif

View File

@ -15,7 +15,6 @@
#include <ctype.h> #include <ctype.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "MathUtils.h"
inline inline
int32 utf8_encode(uint32 codepoint, char* out) int32 utf8_encode(uint32 codepoint, char* out)
@ -80,6 +79,39 @@ int32 utf8_decode(const char* __restrict in, uint32* __restrict codepoint) {
return -1; return -1;
} }
inline
int32 utf8_decode(const uint32 codepoint, char* __restrict out) {
if (codepoint <= 0x7F) {
// 1-byte sequence (ASCII)
out[0] = (char) codepoint;
return 1;
} else if (codepoint <= 0x7FF) {
// 2-byte sequence
out[0] = (char) (0xC0 | ((codepoint >> 6) & 0x1F));
out[1] = (char) (0x80 | (codepoint & 0x3F));
return 2;
} else if (codepoint <= 0xFFFF) {
// 3-byte sequence
out[0] = (char) (0xE0 | ((codepoint >> 12) & 0x0F));
out[1] = (char) (0x80 | ((codepoint >> 6) & 0x3F));
out[2] = (char) (0x80 | (codepoint & 0x3F));
return 3;
} else if (codepoint <= 0x10FFFF) {
// 4-byte sequence
out[0] = (char) (0xF0 | ((codepoint >> 18) & 0x07));
out[1] = (char) (0x80 | ((codepoint >> 12) & 0x3F));
out[2] = (char) (0x80 | ((codepoint >> 6) & 0x3F));
out[3] = (char) (0x80 | (codepoint & 0x3F));
return 4;
}
return -1; // Invalid codepoint
}
inline inline
int32 utf8_strlen(const char* in) { int32 utf8_strlen(const char* in) {
int32 length = 0; int32 length = 0;
@ -400,6 +432,17 @@ int32 str_copy_until(char* __restrict dest, const char* __restrict src, char del
return len; return len;
} }
inline
void str_copy_short(char* __restrict dest, const char* __restrict src, int32 length, char delim = '\0')
{
int32 i = -1;
while (*src != delim && ++i < length) {
*dest++ = *src++;
}
*dest = '\0';
}
inline inline
void str_copy_short(char* __restrict dest, const char* __restrict src, char delim = '\0') void str_copy_short(char* __restrict dest, const char* __restrict src, char delim = '\0')
{ {
@ -981,66 +1024,40 @@ void str_pad(const char* input, char* output, char pad, size_t len) {
} }
} }
void sprintf_fast(char *buffer, const char* format, ...) { void sprintf_fast(char* __restrict buffer, const char* __restrict format, ...) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
const char* ptr = format; while (*format) {
char *buf_ptr = buffer; if (*format != '%') {
*buffer++ = *format;
while (*ptr) { } else if (*format == '\\' && *(format + 1) == '%') {
if (*ptr != '%') { ++format;
*buf_ptr++ = *ptr; *buffer++ = *format;
} else if (*ptr == '\\' && *(ptr + 1) == '%') {
++ptr;
*buf_ptr++ = *ptr;
} else { } else {
++ptr; ++format;
switch (*ptr) { switch (*format) {
case 's': { case 's': {
const char* str = va_arg(args, const char*); const char* str = va_arg(args, const char*);
while (*str) { while (*str) {
*buf_ptr++ = *str++; *buffer++ = *str++;
} }
} break; } break;
case 'c': {
*buffer++ = va_arg(args, char);
} break;
case 'n': {
int64 val = va_arg(args, int64);
buffer += int_to_str(val, buffer, ',');
} break;
case 'd': { case 'd': {
int32 val = va_arg(args, int32); int32 val = va_arg(args, int32);
if (val < 0) { buffer += int_to_str(val, buffer);
*buf_ptr++ = '-';
val = -val;
}
char temp[20];
int32 index = 0;
do {
temp[index++] = (val % 10) + '0';
val /= 10;
} while (val > 0);
while (index > 0) {
*buf_ptr++ = temp[--index];
}
} break; } break;
case 'l': { case 'l': {
int64 val = va_arg(args, int64); int64 val = va_arg(args, int64);
if (val < 0) { buffer += int_to_str(val, buffer);
*buf_ptr++ = '-';
val = -val;
}
char temp[20];
int64 index = 0;
do {
temp[index++] = (val % 10) + '0';
val /= 10;
} while (val > 0);
while (index > 0) {
*buf_ptr++ = temp[--index];
}
} break; } break;
case 'f': { case 'f': {
f64 val = va_arg(args, f64); f64 val = va_arg(args, f64);
@ -1049,7 +1066,7 @@ void sprintf_fast(char *buffer, const char* format, ...) {
int32 precision = 5; int32 precision = 5;
// Check for optional precision specifier // Check for optional precision specifier
const char* prec_ptr = ptr + 1; const char* prec_ptr = format + 1;
if (*prec_ptr >= '0' && *prec_ptr <= '9') { if (*prec_ptr >= '0' && *prec_ptr <= '9') {
precision = 0; precision = 0;
while (*prec_ptr >= '0' && *prec_ptr <= '9') { while (*prec_ptr >= '0' && *prec_ptr <= '9') {
@ -1057,11 +1074,11 @@ void sprintf_fast(char *buffer, const char* format, ...) {
prec_ptr++; prec_ptr++;
} }
ptr = prec_ptr - 1; format = prec_ptr - 1;
} }
if (val < 0) { if (val < 0) {
*buf_ptr++ = '-'; *buffer++ = '-';
val = -val; val = -val;
} }
@ -1087,31 +1104,143 @@ void sprintf_fast(char *buffer, const char* format, ...) {
} while (int_part > 0); } while (int_part > 0);
while (index > 0) { while (index > 0) {
*buf_ptr++ = temp[--index]; *buffer++ = temp[--index];
} }
// Handle fractional part // Handle fractional part
if (precision > 0) { if (precision > 0) {
*buf_ptr++ = '.'; *buffer++ = '.';
while (precision--) { while (precision--) {
frac_part *= 10; frac_part *= 10;
int32 digit = (int32) frac_part; int32 digit = (int32) frac_part;
*buf_ptr++ = (char) (digit + '0'); *buffer++ = (char) (digit + '0');
frac_part -= digit; frac_part -= digit;
} }
} }
} break; } break;
default: { default: {
// Handle unknown format specifiers // Handle unknown format specifiers
*buf_ptr++ = '%'; *buffer++ = '%';
} break; } break;
} }
} }
++ptr; ++format;
} }
*buf_ptr = '\0'; *buffer = '\0';
va_end(args);
}
// There are situations where you only want to replace a certain amount of %
void sprintf_fast_iter(char* buffer, const char* format, ...) {
va_list args;
va_start(args, format);
int32 count_index = 0;
while (*format) {
if (*format != '%' || count_index >= 1) {
*buffer++ = *format;
} else if (*format == '\\' && *(format + 1) == '%') {
++format;
*buffer++ = *format;
} else {
++count_index;
++format;
switch (*format) {
case 's': {
const char* str = va_arg(args, const char*);
while (*str) {
*buffer++ = *str++;
}
} break;
case 'c': {
*buffer++ = va_arg(args, char);
} break;
case 'n': {
int64 val = va_arg(args, int64);
buffer += int_to_str(val, buffer, ',');
} break;
case 'd': {
int32 val = va_arg(args, int32);
buffer += int_to_str(val, buffer);
} break;
case 'l': {
int64 val = va_arg(args, int64);
buffer += int_to_str(val, buffer);
} break;
case 'f': {
f64 val = va_arg(args, f64);
// Default precision
int32 precision = 5;
// Check for optional precision specifier
const char* prec_ptr = format + 1;
if (*prec_ptr >= '0' && *prec_ptr <= '9') {
precision = 0;
while (*prec_ptr >= '0' && *prec_ptr <= '9') {
precision = precision * 10 + (*prec_ptr - '0');
prec_ptr++;
}
format = prec_ptr - 1;
}
if (val < 0) {
*buffer++ = '-';
val = -val;
}
if (precision < 6) {
static const float powers_of_ten[] = {
1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f, 100000.0f
};
f32 scale = powers_of_ten[precision];
val = OMS_ROUND_POSITIVE(val * scale) / scale;
}
// Handle integer part
int32 int_part = (int32) val;
f64 frac_part = val - int_part;
char temp[20];
int32 index = 0;
do {
temp[index++] = (int_part % 10) + '0';
int_part /= 10;
} while (int_part > 0);
while (index > 0) {
*buffer++ = temp[--index];
}
// Handle fractional part
if (precision > 0) {
*buffer++ = '.';
while (precision--) {
frac_part *= 10;
int32 digit = (int32) frac_part;
*buffer++ = (char) (digit + '0');
frac_part -= digit;
}
}
} break;
default: {
// Handle unknown format specifiers
*buffer++ = '%';
} break;
}
}
++format;
}
*buffer = '\0';
va_end(args); va_end(args);
} }