From a02963607d8b0d5a02ea3a08309699213ac11f23 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Jan 2025 01:26:44 +0100 Subject: [PATCH] bug fixes, improved input handling and started testing with typing mode --- animation/Animation.h | 2 +- asset/AssetArchive.h | 10 + asset/AssetManagementSystem.h | 16 +- audio/AudioMixer.h | 1 - auth/Auth.h | 1 - command/AppCmdBuffer.cpp | 2 + compression/Huffman.h | 1 - entity/EntityComponentSystem.h | 2 +- environment/Globe.h | 1 - gpuapi/RenderUtils.h | 14 +- gpuapi/direct3d/ShaderUtils.h | 2 +- gpuapi/opengl/OpenglUtils.h | 3 +- gpuapi/opengl/ShaderUtils.h | 4 +- gpuapi/vulkan/ShaderUtils.h | 2 +- gpuapi/vulkan/VulkanUtils.h | 32 +- image/Bitmap.h | 1 - image/default_colors.h | 32 +- input/Input.h | 653 ++++++++++--------- log/Debug.cpp | 192 +++--- log/Debug.h | 49 +- log/DebugMemory.h | 12 +- log/Log.h | 56 +- math/matrix/MatrixFloat32.h | 3 +- math/matrix/MatrixInt32.h | 2 - math/matrix/MatrixInt64.h | 2 - math/matrix/QuaternionFloat32.h | 7 +- math/matrix/VectorFloat32.h | 1 - math/matrix/VectorFloat64.h | 1 - math/matrix/VectorInt32.h | 1 - math/matrix/VectorInt64.h | 1 - memory/BufferMemory.h | 15 +- memory/ChunkMemory.h | 25 +- memory/Heap.h | 10 +- memory/RingMemory.h | 23 +- models/mob/Mob.cpp | 1 - models/mob/monster/LootTable.h | 1 - pathfinding/Jpsp.h | 1 - pathfinding/Metric2d.h | 1 - pathfinding/Path.h | 1 - pathfinding/jps/Jps.h | 1 - pathfinding/jps/JpsGrid.h | 1 - pathfinding/jps/JpsNode.h | 1 - platform/win32/Allocator.h | 5 +- platform/win32/SystemInfo.cpp | 1 + platform/win32/UtilsWin32.h | 17 + platform/win32/Window.h | 2 + platform/win32/audio/DirectSound.h | 15 +- platform/win32/audio/Wasapi.h | 21 +- platform/win32/audio/XAudio2.h | 12 +- platform/win32/input/HidInput.h | 2 +- platform/win32/input/RawInput.h | 81 +-- platform/win32/input/XInput.h | 1 - platform/win32/input/controller/DualSense.h | 1 - platform/win32/input/controller/DualShock4.h | 1 - platform/win32/threading/Atomic.h | 16 +- stdlib/HashMap.h | 18 +- stdlib/Types.h | 40 ++ thread/Thread.h | 2 + thread/ThreadPool.h | 5 +- utils/MathUtils.h | 38 -- utils/StringUtils.h | 239 +++++-- 61 files changed, 949 insertions(+), 755 deletions(-) delete mode 100644 utils/MathUtils.h diff --git a/animation/Animation.h b/animation/Animation.h index 9582c04..92c9798 100644 --- a/animation/Animation.h +++ b/animation/Animation.h @@ -10,8 +10,8 @@ #ifndef TOS_ANIMATION_H #define TOS_ANIMATION_H +#include #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" #include "AnimationEaseType.h" diff --git a/asset/AssetArchive.h b/asset/AssetArchive.h index 98e4227..5ddba8d 100644 --- a/asset/AssetArchive.h +++ b/asset/AssetArchive.h @@ -165,6 +165,11 @@ void asset_archive_load(AssetArchive* archive, const char* path, BufferMemory* b file.content = ring_get_memory(ring, file.size); file_read(archive->fd, &file, 0, file.size); 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? @@ -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 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 // @bug dependencies might be stored in different archives? for (uint32 i = 0; i < element->dependency_count; ++i) { diff --git a/asset/AssetManagementSystem.h b/asset/AssetManagementSystem.h index 0edd87d..cb7fb64 100644 --- a/asset/AssetManagementSystem.h +++ b/asset/AssetManagementSystem.h @@ -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); ams->asset_component_count = asset_component_count; 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 @@ -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); 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 @@ -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); 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 @@ -216,7 +222,7 @@ Asset* thrd_ams_get_reserve_asset_wait(AssetManagementSystem* ams, byte type, co ac->ram_size += asset->ram_size; ++ac->asset_count; - DEBUG_MEMORY_RESERVE((uint64) asset, asset->ram_size, 180); + DEBUG_MEMORY_RESERVE((uintptr_t) asset, asset->ram_size, 180); return asset; } @@ -389,7 +395,7 @@ Asset* ams_reserve_asset(AssetManagementSystem* ams, byte type, const char* name ac->ram_size += asset->ram_size; ++ac->asset_count; - DEBUG_MEMORY_RESERVE((uint64) asset, asset->ram_size, 180); + DEBUG_MEMORY_RESERVE((uintptr_t) asset, asset->ram_size, 180); return asset; } @@ -422,7 +428,7 @@ Asset* thrd_ams_reserve_asset(AssetManagementSystem* ams, byte type, const char* ac->ram_size += asset.ram_size; ++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); @@ -499,7 +505,7 @@ Asset* ams_insert_asset(AssetManagementSystem* ams, Asset* asset_temp, const cha ++ac->asset_count; 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; } @@ -530,7 +536,7 @@ Asset* thrd_ams_insert_asset(AssetManagementSystem* ams, Asset* asset_temp, cons ++ac->asset_count; 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); diff --git a/audio/AudioMixer.h b/audio/AudioMixer.h index 677e384..48892ae 100644 --- a/audio/AudioMixer.h +++ b/audio/AudioMixer.h @@ -13,7 +13,6 @@ #include "Audio.h" #include "AudioSetting.h" #include "../utils/Utils.h" -#include "../utils/MathUtils.h" #include "../memory/ChunkMemory.h" #include "../math/matrix/MatrixFloat32.h" #include "../thread/Atomic.h" diff --git a/auth/Auth.h b/auth/Auth.h index c757415..4084b95 100644 --- a/auth/Auth.h +++ b/auth/Auth.h @@ -14,7 +14,6 @@ #include #include "../../EngineDependencies/curl/include/curl/curl.h" -#include "../utils/MathUtils.h" #define MAX_AUTH_POST_LENGTH 1024 #define MAX_AUTH_RESPONSE_LENGTH 1024 diff --git a/command/AppCmdBuffer.cpp b/command/AppCmdBuffer.cpp index 21f811e..c45a633 100644 --- a/command/AppCmdBuffer.cpp +++ b/command/AppCmdBuffer.cpp @@ -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); 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 diff --git a/compression/Huffman.h b/compression/Huffman.h index 1cd764d..801ee04 100644 --- a/compression/Huffman.h +++ b/compression/Huffman.h @@ -14,7 +14,6 @@ #include "../stdlib/Types.h" #include "../utils/BitUtils.h" -#include "../utils/MathUtils.h" #include "../utils/EndianUtils.h" struct HuffmanNode { diff --git a/entity/EntityComponentSystem.h b/entity/EntityComponentSystem.h index cc97493..67224f4 100644 --- a/entity/EntityComponentSystem.h +++ b/entity/EntityComponentSystem.h @@ -108,7 +108,7 @@ Entity* ecs_insert_entity(EntityComponentSystem* ecs, Entity* entity_temp, int32 memcpy(entity, entity_temp, mem->chunk_size); // @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; } diff --git a/environment/Globe.h b/environment/Globe.h index c95a107..c46de5b 100644 --- a/environment/Globe.h +++ b/environment/Globe.h @@ -2,7 +2,6 @@ #define TOS_ENVIRONMENT_GLOBE_H #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" #include /** diff --git a/gpuapi/RenderUtils.h b/gpuapi/RenderUtils.h index 17cc179..21c2dd9 100644 --- a/gpuapi/RenderUtils.h +++ b/gpuapi/RenderUtils.h @@ -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 // 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( Vertex3DTextureColorIndex* __restrict vertices, uint32* __restrict index, f32 zindex, 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; for (int32 i = 0; i < length; ++i) { int32 character = is_ascii ? text[i] : utf8_get_char_at(text, i); 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; continue; @@ -429,7 +439,7 @@ v2_f32 vertex_text_create( // This way we can ensure no overflow easily // @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 diff --git a/gpuapi/direct3d/ShaderUtils.h b/gpuapi/direct3d/ShaderUtils.h index 6bb1208..1e216b3 100644 --- a/gpuapi/direct3d/ShaderUtils.h +++ b/gpuapi/direct3d/ShaderUtils.h @@ -41,7 +41,7 @@ ID3D12PipelineState* program_make( HRESULT hr = device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)); if (FAILED(hr)) { - LOG("Failed to create program", true, true); + LOG(true, "Failed to create program"); return NULL; } diff --git a/gpuapi/opengl/OpenglUtils.h b/gpuapi/opengl/OpenglUtils.h index dd5d0b0..d3c41ba 100644 --- a/gpuapi/opengl/OpenglUtils.h +++ b/gpuapi/opengl/OpenglUtils.h @@ -44,7 +44,7 @@ void opengl_debug_callback(GLenum source, GLenum type, GLuint id, GLenum severit return; } - LOG(message, true, true); + LOG(true, message); ASSERT_SIMPLE(false); } @@ -490,6 +490,7 @@ void gpuapi_error() { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { + LOG_FORMAT(true, "Opengl error: %d", {{LOG_DATA_INT32, (int32 *) &err}}); ASSERT_SIMPLE(err == GL_NO_ERROR); } } diff --git a/gpuapi/opengl/ShaderUtils.h b/gpuapi/opengl/ShaderUtils.h index fb38b9e..9759822 100644 --- a/gpuapi/opengl/ShaderUtils.h +++ b/gpuapi/opengl/ShaderUtils.h @@ -275,7 +275,7 @@ GLuint shader_make(GLenum type, const char* source, RingMemory* ring) GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); glGetShaderInfoLog(shader, length, NULL, info); - LOG(info, true, true); + LOG(true, info); ASSERT_SIMPLE(false); } @@ -321,7 +321,7 @@ GLuint program_make( GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); glGetProgramInfoLog(program, length, NULL, info); - LOG(info, true, true); + LOG(true, info); ASSERT_SIMPLE(false); } diff --git a/gpuapi/vulkan/ShaderUtils.h b/gpuapi/vulkan/ShaderUtils.h index 404fb9d..599af61 100644 --- a/gpuapi/vulkan/ShaderUtils.h +++ b/gpuapi/vulkan/ShaderUtils.h @@ -58,7 +58,7 @@ VkShaderModule shader_make(VkDevice device, const char* source, int32 source_siz VkResult result = vkCreateShaderModule(device, &create_info, NULL, &shader_module); if (result != VK_SUCCESS) { - LOG("Failed to create shader module", true, true); + LOG(true, "Failed to create shader module"); ASSERT_SIMPLE(false); return VK_NULL_HANDLE; diff --git a/gpuapi/vulkan/VulkanUtils.h b/gpuapi/vulkan/VulkanUtils.h index fd15578..5b91900 100644 --- a/gpuapi/vulkan/VulkanUtils.h +++ b/gpuapi/vulkan/VulkanUtils.h @@ -111,7 +111,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_callback( if ((severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_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; @@ -158,14 +158,14 @@ void vulkan_instance_create( if (validation_layer_count && (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); } if (extension_count && (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); } @@ -195,7 +195,7 @@ void vulkan_instance_create( VkResult result; 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); } } @@ -210,7 +210,7 @@ void vulkan_surface_create(VkInstance instance, VkSurfaceKHR* surface, Window* w VkResult result; 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; } #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); } @@ -392,7 +392,7 @@ void gpuapi_create_logical_device( VkResult result; 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); } @@ -480,7 +480,7 @@ void vulkan_swap_chain_create( VkResult result; 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); } @@ -521,7 +521,7 @@ void vulkan_image_views_create( create_info.subresourceRange.layerCount = 1; 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); } } @@ -568,7 +568,7 @@ void create_render_pass( VkResult result; 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); } } @@ -665,7 +665,7 @@ void vulkan_pipeline_create( VkResult result; 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); } @@ -686,7 +686,7 @@ void vulkan_pipeline_create( pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; 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); } @@ -717,7 +717,7 @@ void vulkan_framebuffer_create( framebufferInfo.layers = 1; 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); } } @@ -736,7 +736,7 @@ void vulkan_command_pool_create( VkResult result; 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); } } @@ -751,7 +751,7 @@ void vulkan_command_buffer_create(VkDevice device, VkCommandBuffer* command_buff VkResult result; 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); } } @@ -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 = 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); } diff --git a/image/Bitmap.h b/image/Bitmap.h index e2faec4..5e07773 100644 --- a/image/Bitmap.h +++ b/image/Bitmap.h @@ -15,7 +15,6 @@ #include "../stdlib/Types.h" #include "../utils/Utils.h" #include "../utils/EndianUtils.h" -#include "../utils/MathUtils.h" #include "Image.h" // See: https://en.wikipedia.org/wiki/BMP_file_format diff --git a/image/default_colors.h b/image/default_colors.h index c6c02d4..6eee2a4 100644 --- a/image/default_colors.h +++ b/image/default_colors.h @@ -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) const uint32 default_colors_256[256] = { - 0xFFFFFF00, 0xFFFFFFFF, 0xF1EEEDFF, 0xDCDEDEFF, 0xBFC1BFFF, 0xAEB0ADFF, 0x9E9D9EFF, 0x8E8F94FF, 0x717373FF, 0x5E5F61FF, 0x4D4D4CFF, 0x3F403AFF, 0x332C2AFF, 0x241E22FF, 0x0C1210FF, 0x000000FF, - 0xF6D3CFFF, 0xFABABCFF, 0xFBA699FF, 0xF19580FF, 0xFB837AFF, 0xFC615AFF, 0xFF4E4BFF, 0xFF4040FF, 0xF72128FF, 0xF60303FF, 0xE40000FF, 0xC70002FF, 0x900009FF, 0x630604FF, 0x4f0107FF, 0x2d0205FF, - 0xFDDDCEFF, 0xFCC5ACFF, 0xFFB9A4FF, 0xF6A378FF, 0xF49A80FF, 0xFF7D4FFF, 0xF8742CFF, 0xFE5A22FF, 0xF44A0BFF, 0xDA3A06FF, 0xC03500FF, 0x853004FF, 0x912600FF, 0x672300FF, 0x471608FF, 0x2b0d05FF, - 0xFCEBCFFF, 0xFCD8AAFF, 0xFFCD98FF, 0xFCC27FFF, 0xF3B267FF, 0xFDA660FF, 0xFD942DFF, 0xFF8001FF, 0xDF6E00FF, 0xCC6B00FF, 0xA85D00FF, 0xA55300FF, 0x734700FF, 0x612D08FF, 0x562600FF, 0x351700FF, - 0xFFF6C9FF, 0xFFECA8FF, 0xFDE884FF, 0xFADC6DFF, 0xF8DE6FFF, 0xFFCF43FF, 0xFFBD00FF, 0xEBB800FF, 0xC1A800FF, 0xBC8F09FF, 0x9B7A00FF, 0x8E6C08FF, 0x795F01FF, 0x5C4A00FF, 0x523B00FF, 0x392900FF, - 0xFFFFCDFF, 0xFDFEAFFF, 0xFCFBA1FF, 0xFDFF69FF, 0xF9FF2AFF, 0xFFFE04FF, 0xEFEE00FF, 0xE0DE00FF, 0xBDBF13FF, 0xB4AF00FF, 0x9F9900FF, 0x909002FF, 0x717300FF, 0x505400FF, 0x4A4F00FF, 0x343700FF, - 0xE4FFBDFF, 0xDFFEB9FF, 0xD1FF8FFF, 0xCAFC84FF, 0xC0F96BFF, 0xBAF353FF, 0x98FB00FF, 0x9AEE0FFF, 0x78CE00FF, 0x74C100FF, 0x61A401FF, 0x578A03FF, 0x4F7E02FF, 0x3C6200FF, 0x2E4F00FF, 0x203700FF, - 0xE1F8D8FF, 0xBBFEADFF, 0xA2F592FF, 0xA1F79AFF, 0x81FF7AFF, 0x5DFF59FF, 0x48FF58FF, 0x00F600FF, 0x12D31FFF, 0x0ACB04FF, 0x10A40AFF, 0x089811FF, 0x06780EFF, 0x05640FFF, 0x005200FF, 0x003100FF, - 0xD5FFF8FF, 0xBCFFEAFF, 0xA7FED3FF, 0x99F2C4FF, 0x6CFFB5FF, 0x53F29EFF, 0x4CFEA1FF, 0x0AF779FF, 0x0CD56AFF, 0x0BC868FF, 0x01AA50FF, 0x07A557FF, 0x008642FF, 0x075A30FF, 0x00562CFF, 0x00331aFF, - 0xD9FDFEFF, 0xB3FCFFFF, 0xACFFFFFF, 0x90FFFFFF, 0x76FEFFFF, 0x5FFAFDFF, 0x08FEFEFF, 0x22F3F2FF, 0x06C9C2FF, 0x08B2C4FF, 0x049FA4FF, 0x078C97FF, 0x008286FF, 0x025D5DFF, 0x005056FF, 0x003135FF, - 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, - 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, - 0xFFC7FFFF, 0xFFB2FFFF, 0xFF9AFFFF, 0xF181F1FF, 0xFB6FFDFF, 0xF850FBFF, 0xFB46FFFF, 0xF91FFFFF, 0xF900FFFF, 0xDD00E6FF, 0xBF00C7FF, 0x9B0199FF, 0xB70090FF, 0x670362FF, 0x4F0153FF, 0x330035FF, - 0xFDD2E6FF, 0xF9B5DAFF, 0xF7A4D4FF, 0xF198CBFF, 0xF682BDFF, 0xFF5FAEFF, 0xFF4CA9FF, 0xFF3CA4FF, 0xFF1A94FF, 0xF90979FF, 0xE80071FF, 0xC40061FF, 0x96004AFF, 0x670132FF, 0x4F0024FF, 0x310016FF + 0xFFFFFF00, 0xFFFFFFFF, 0xE9E9E9FF, 0xD9D9D9FF, 0xC9C9C9FF, 0xB9B9B9FF, 0xA9A9A9FF, 0x999999FF, 0x898989FF, 0x797979FF, 0x696969FF, 0x595959FF, 0x494949FF, 0x393939FF, 0x1F1F1FFF, 0x000000FF, + 0xF6D3CFFF, 0xF8C2BDFF, 0xFB9E91FF, 0xFC8B7EFF, 0xFC796CFF, 0xFD675BFF, 0xFF554BFF, 0xFF4340FF, 0xF82D2EFF, 0xF6171BFF, 0xE60412FF, 0xCC0004FF, 0xA70004FF, 0x7A0306FF, 0x4f0107FF, 0x330004FF, + 0xFDDDCEFF, 0xFCCFB6FF, 0xFDB69EFF, 0xF5A78CFF, 0xF69B7EFF, 0xFF8A65FF, 0xFF7A50FF, 0xFB683AFF, 0xF95523FF, 0xF34413FF, 0xD8390AFF, 0xB22F07FF, 0x8F2905FF, 0x742406FF, 0x57200AFF, 0x2b0d05FF, + 0xFCEBCFFF, 0xFCDAB2FF, 0xFCCB96FF, 0xFBBE7CFF, 0xF3B067FF, 0xFCA45FFF, 0xFB913EFF, 0xFF7F1CFF, 0xE76E09FF, 0xD06B00FF, 0xB05F00FF, 0x9C5300FF, 0x824A00FF, 0x6E3B06FF, 0x5A2E05FF, 0x351700FF, + 0xFFF6C9FF, 0xFFEDB1FF, 0xFFE593FF, 0xFDDC74FF, 0xF9D36AFF, 0xFFC94FFF, 0xFFBD1EFF, 0xF4B600FF, 0xD2A200FF, 0xB78E04FF, 0x9D7D00FF, 0x8C6F07FF, 0x776300FF, 0x614F00FF, 0x503D00FF, 0x392900FF, + 0xFFFFCDFF, 0xFEFDBCFF, 0xFCF9A3FF, 0xFBF583FF, 0xFAF065FF, 0xFFEA2BFF, 0xFEEB04FF, 0xE9DC00FF, 0xD7CC00FF, 0xC4BA00FF, 0xADA500FF, 0x9A9200FF, 0x7C7700FF, 0x605B00FF, 0x4F4C00FF, 0x343700FF, + 0xE4FFBDFF, 0xDBFDBCFF, 0xCEF9A3FF, 0xC4F48EFF, 0xBAEE76FF, 0xB1E760FF, 0x9FEF29FF, 0x97E313FF, 0x7FC900FF, 0x78BB00FF, 0x67A201FF, 0x5C8E02FF, 0x527F01FF, 0x426600FF, 0x334F00FF, 0x203700FF, + 0xE1F8D8FF, 0xC7F8C2FF, 0xADF5ABFF, 0x9EEC97FF, 0x85E47FFF, 0x66DF66FF, 0x4EDB5FFF, 0x23D138FF, 0x12C72CFF, 0x0EB522FF, 0x109B17FF, 0x0A8913FF, 0x077311FF, 0x066011FF, 0x004F06FF, 0x003100FF, + 0xD5FFF8FF, 0xC5FDF4FF, 0xA8F7E5FF, 0x99F0D7FF, 0x7BF1C6FF, 0x60E6B1FF, 0x53E0A0FF, 0x1CE76FFF, 0x0DD763FF, 0x0AD056FF, 0x02B548FF, 0x04A94DFF, 0x009A40FF, 0x088133FF, 0x005A2BFF, 0x00331AFF, + 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, + 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, + 0xE1D4FFFF, 0xD8ACFFFF, 0xCD9BFFFF, 0xC88DFAFF, 0xBD8AF9FF, 0xB160FFFF, 0xAA52FEFF, 0x9841FDFF, 0x8726FFFF, 0x8700F5FF, 0x7200F4FF, 0x5C00B7FF, 0x460489FF, 0x350077FF, 0x28004FFF, 0x1c0037FF, + 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, }; // @todo Implement (extends the default_colors_256 -> both together form 1024 colors) diff --git a/input/Input.h b/input/Input.h index 107c656..b35d9c5 100644 --- a/input/Input.h +++ b/input/Input.h @@ -28,7 +28,7 @@ // How many concurrent primary key/button presses can be handled? #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 #define MAX_KEYBOARD_KEYS 255 @@ -36,10 +36,6 @@ #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 #define MAX_HOTKEY_COMBINATION 3 @@ -63,6 +59,7 @@ enum InputType { #ifdef _WIN32 #include #include + #include "../platform/win32/UtilsWin32.h" #endif 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 // Having separate keyboard_down and mouse_down etc. is a little bit weird in the functions below -struct InputMapping { - // A key/button can be bound to up to 5 different hotkeys - // This is used to check if a key/button has a hotkey association - uint8 keys[MEX_KEY_LENGTH]; - - // A hotkey can be bound to a combination of up to 3 key/button presses - uint8 hotkey_count; +enum KeyPressType : byte { + KEY_PRESS_TYPE_NONE, + KEY_PRESS_TYPE_PRESSED, + KEY_PRESS_TYPE_HELD, + KEY_PRESS_TYPE_RELEASED, +}; +struct Hotkey { // 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 // index = hotkey, value = key id - int16* hotkeys; - InputCallback* callbacks; + int16 scan_codes[MAX_HOTKEY_COMBINATION]; + KeyPressType key_state; + InputCallback callback; }; -enum KeyState { - KEY_STATE_PRESSED, - KEY_STATE_HELD, - KEY_STATE_RELEASED, +struct InputMapping { + // A hotkey can be bound to a combination of up to 3 key/button presses + // The indices represent the hotkey id + uint8 hotkey_count; + Hotkey* hotkeys; }; struct InputKey { // Includes flag for mouse, keyboard, controller - uint16 key_id; - uint16 key_state; - int16 value; // e.g. stick/trigger keys have additional values + uint16 scan_code; + uint16 virtual_code; + KeyPressType key_state; 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 // Or think about completely splitting all states (mouse, keyboard, other) struct InputState { - // State of the hotkeys, resulting from the device input - uint8 state_hotkeys[MAX_KEY_PRESSES]; + // Active hotkeys + 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 dy; @@ -128,6 +131,13 @@ struct InputState { 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 { // Device InputConnectionType connection_type; @@ -145,17 +155,15 @@ struct Input { #endif byte controller_type; - bool state_change_button; - 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; + byte general_states; InputState state; 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 characters[10]; // This data is passed to the hotkey callback void* callback_data; @@ -172,247 +180,202 @@ void input_init(Input* input, uint8 size, void* callback_data, BufferMemory* buf // Init mapping1 input->input_mapping1.hotkey_count = size; - - input->input_mapping1.hotkeys = (int16 *) buffer_get_memory( + input->input_mapping1.hotkeys = (Hotkey *) buffer_get_memory( buf, - input->input_mapping1.hotkey_count * MAX_HOTKEY_COMBINATION * sizeof(int16) - ); - - input->input_mapping1.callbacks = (InputCallback *) buffer_get_memory( - buf, - input->input_mapping1.hotkey_count * sizeof(InputCallback), - 0, true + input->input_mapping1.hotkey_count * sizeof(Hotkey), + 4, true ); // Init mapping2 input->input_mapping2.hotkey_count = size; - - input->input_mapping2.hotkeys = (int16 *) buffer_get_memory( + input->input_mapping2.hotkeys = (Hotkey *) buffer_get_memory( buf, - input->input_mapping2.hotkey_count * MAX_HOTKEY_COMBINATION * sizeof(int16) - ); - - input->input_mapping2.callbacks = (InputCallback *) buffer_get_memory( - buf, - input->input_mapping2.hotkey_count * sizeof(InputCallback), - 0, true + input->input_mapping2.hotkey_count * sizeof(Hotkey), + 4, true ); } 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 (state_keys[i].key_state == KEY_STATE_RELEASED) { - state_keys[i].key_id = 0; + if (press_status) { + for (int32 i = 0; i < MAX_KEY_PRESS_TYPES; ++i) { + 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 -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 - || state_keys[1].key_id == key - || state_keys[2].key_id == key - || state_keys[3].key_id == key - || state_keys[4].key_id == key - || state_keys[4].key_id == key - || state_keys[5].key_id == key - || state_keys[6].key_id == key - || state_keys[7].key_id == key - || state_keys[8].key_id == key - || state_keys[9].key_id == key; + return (active_keys[0].scan_code == key && active_keys[0].key_state == press_type) + || (active_keys[1].scan_code == key && active_keys[1].key_state == press_type) + || (active_keys[2].scan_code == key && active_keys[2].key_state == press_type) + || (active_keys[3].scan_code == key && active_keys[3].key_state == press_type) + || (active_keys[4].scan_code == key && active_keys[4].key_state == press_type) + || (active_keys[4].scan_code == key && active_keys[4].key_state == press_type) + || (active_keys[5].scan_code == key && active_keys[5].key_state == press_type) + || (active_keys[6].scan_code == key && active_keys[6].key_state == press_type) + || (active_keys[7].scan_code == key && active_keys[7].key_state == press_type) + || (active_keys[8].scan_code == key && active_keys[8].key_state == press_type) + || (active_keys[9].scan_code == key && active_keys[9].key_state == press_type); } 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) - || (state_keys[1].key_id == key && state_keys[1].key_state != KEY_STATE_RELEASED) - || (state_keys[2].key_id == key && state_keys[2].key_state != KEY_STATE_RELEASED) - || (state_keys[3].key_id == key && state_keys[3].key_state != KEY_STATE_RELEASED) - || (state_keys[4].key_id == key && state_keys[4].key_state != KEY_STATE_RELEASED) - || (state_keys[5].key_id == key && state_keys[5].key_state != KEY_STATE_RELEASED) - || (state_keys[6].key_id == key && state_keys[6].key_state != KEY_STATE_RELEASED) - || (state_keys[7].key_id == key && state_keys[7].key_state != KEY_STATE_RELEASED) - || (state_keys[8].key_id == key && state_keys[8].key_state != KEY_STATE_RELEASED) - || (state_keys[9].key_id == key && state_keys[9].key_state != KEY_STATE_RELEASED); + return (active_keys[0].scan_code == key && active_keys[0].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[1].scan_code == key && active_keys[1].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[2].scan_code == key && active_keys[2].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[3].scan_code == key && active_keys[3].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[4].scan_code == key && active_keys[4].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[5].scan_code == key && active_keys[5].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[6].scan_code == key && active_keys[6].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[7].scan_code == key && active_keys[7].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[8].scan_code == key && active_keys[8].key_state != KEY_PRESS_TYPE_RELEASED) + || (active_keys[9].scan_code == key && active_keys[9].key_state != KEY_PRESS_TYPE_RELEASED); } 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) - || (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_PRESSED) - || (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_PRESSED) - || (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_PRESSED) - || (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_PRESSED) - || (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_PRESSED) - || (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_PRESSED) - || (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_PRESSED) - || (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_PRESSED) - || (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_PRESSED); + return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_PRESSED) + || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_PRESSED); } 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) - || (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_HELD) - || (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_HELD) - || (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_HELD) - || (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_HELD) - || (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_HELD) - || (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_HELD) - || (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_HELD) - || (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_HELD) - || (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_HELD) - || (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_HELD); + return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_HELD) + || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_HELD); } 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) - || (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_RELEASED) - || (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_RELEASED) - || (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_RELEASED) - || (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) - || (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) - || (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_RELEASED) - || (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_RELEASED) - || (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_RELEASED) - || (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_RELEASED) - || (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_RELEASED); + return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_RELEASED); } 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) - || (state_keys[1].key_id == key && state_keys[1].key_state == KEY_STATE_RELEASED) - || (state_keys[2].key_id == key && state_keys[2].key_state == KEY_STATE_RELEASED) - || (state_keys[3].key_id == key && state_keys[3].key_state == KEY_STATE_RELEASED) - || (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) - || (state_keys[4].key_id == key && state_keys[4].key_state == KEY_STATE_RELEASED) - || (state_keys[5].key_id == key && state_keys[5].key_state == KEY_STATE_RELEASED) - || (state_keys[6].key_id == key && state_keys[6].key_state == KEY_STATE_RELEASED) - || (state_keys[7].key_id == key && state_keys[7].key_state == KEY_STATE_RELEASED) - || (state_keys[8].key_id == key && state_keys[8].key_state == KEY_STATE_RELEASED) - || (state_keys[9].key_id == key && state_keys[9].key_state == KEY_STATE_RELEASED); + return (active_keys[0].scan_code == key && active_keys[0].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[1].scan_code == key && active_keys[1].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[2].scan_code == key && active_keys[2].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[3].scan_code == key && active_keys[3].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[4].scan_code == key && active_keys[4].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[5].scan_code == key && active_keys[5].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[6].scan_code == key && active_keys[6].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[7].scan_code == key && active_keys[7].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[8].scan_code == key && active_keys[8].key_state == KEY_PRESS_TYPE_RELEASED) + || (active_keys[9].scan_code == key && active_keys[9].key_state == KEY_PRESS_TYPE_RELEASED); } inline 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 ) { - return (key0 != 0 && input_is_down(state_keys, key0)) - && (key1 == 0 || input_is_down(state_keys, key1)) - && (key2 == 0 || input_is_down(state_keys, key2)) - && (key3 == 0 || input_is_down(state_keys, key3)) - && (key4 == 0 || input_is_down(state_keys, key4)); + return (key0 != 0 && input_is_down(active_keys, key0)) + && (key1 == 0 || input_is_down(active_keys, key1)) + && (key2 == 0 || input_is_down(active_keys, key2)) + && (key3 == 0 || input_is_down(active_keys, key3)) + && (key4 == 0 || input_is_down(active_keys, key4)); } 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 input_add_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; + mapping->hotkeys[(hotkey - 1)].key_state = press_type; + // 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) - mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION] = (int16) key0; - ++count; + mapping->hotkeys[(hotkey - 1)].scan_codes[count++] = key1; + 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) - mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + count] = (int16) key1; - ++count; - } - - 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 - } + mapping->hotkeys[(hotkey - 1)].scan_codes[count++] = key2; + key2 = OMS_ABS_INT16(key2); } } 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 - || state_hotkeys[1] == hotkey - || state_hotkeys[2] == hotkey - || state_hotkeys[3] == hotkey - || state_hotkeys[4] == hotkey; + return active_hotkeys[0] == hotkey + || active_hotkeys[1] == hotkey + || active_hotkeys[2] == hotkey + || active_hotkeys[3] == hotkey + || active_hotkeys[4] == hotkey; } // 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) 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 key1 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 1]; - int16 key2 = mapping->hotkeys[(hotkey - 1) * MAX_HOTKEY_COMBINATION + 2]; + int16 key0 = mapping->hotkeys[(hotkey - 1)].scan_codes[0]; + int16 key1 = mapping->hotkeys[(hotkey - 1)].scan_codes[1]; + 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 // 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 // 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)); - if ((!is_active && (key0 > 0 || key1 >= 0)) || (is_active && key0 < 0)) { + 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) || (key1 == 0 && key2 == 0)) { return is_active; } - is_active = input_action_exists(state_keys, (int16) OMS_ABS(key1)); - if ((!is_active && (key1 > 0 || key2 >= 0)) || (is_active && key1 < 0)) { + 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) || (key2 == 0)) { 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 -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; - bool action_required = true; - for (int32 i = 0; i < MAX_KEY_STATES; ++i) { - if (!free_state && state_keys[i].key_id == 0) { - free_state = &state_keys[i]; - } else if (state_keys[i].key_id == new_key->key_id) { - state_keys[i].key_state = new_key->key_state; - state_keys[i].value += new_key->value; - state_keys[i].time = new_key->time; - action_required = false; + // Insert new key state or change if key already exists + for (int32 i = 0; i < MAX_KEY_PRESS_TYPES; ++i) { + if (!free_state && active_keys[i].scan_code == 0) { + free_state = &active_keys[i]; + } else if (active_keys[i].scan_code == new_key->scan_code) { + active_keys[i].key_state = new_key->key_state; + active_keys[i].value += new_key->value; + active_keys[i].time = new_key->time; + + return; } } - if (!action_required || !free_state) { + if (!free_state) { 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->value = new_key->value; 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 for (int32 i = 0; i < MAX_KEY_PRESSES; ++i) { - if ((input->state.state_keys[i].key_id & INPUT_CONTROLLER_PREFIX) - && input->state.state_keys[i].key_state != KEY_STATE_RELEASED + if ((input->state.active_keys[i].scan_code & INPUT_CONTROLLER_PREFIX) + && 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) - || (!controller->is_analog[key_id] && controller->button[key_id] == 0) + if ((controller->is_analog[scan_code] && OMS_ABS_INT8(controller->button[scan_code]) < input->deadzone) + || (!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 // @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) - 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_change_mouse = true; + input->general_states |= INPUT_STATE_GENERAL_MOUSE_CHANGE; } else { 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_change_mouse = true; + input->general_states |= INPUT_STATE_GENERAL_MOUSE_CHANGE; } else { 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; // @todo needs state change flag like mouse?! } else { 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; // @todo needs state change flag like mouse?! } else { @@ -519,11 +484,11 @@ void input_set_controller_state(Input* input, ControllerInput* controller, uint6 InputKey keys[5]; 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) ) { - keys[count].key_id = i | INPUT_CONTROLLER_PREFIX; - keys[count].key_state = KEY_STATE_PRESSED; + keys[count].scan_code = i | INPUT_CONTROLLER_PREFIX; + keys[count].key_state = KEY_PRESS_TYPE_PRESSED; keys[count].value = controller->button[i]; keys[count].time = time; @@ -533,102 +498,117 @@ void input_set_controller_state(Input* input, ControllerInput* controller, uint6 if (count > 0) { 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 -input_hotkey_state(Input* input) +void input_hotkey_state(Input* input) { - uint8 old_hotkeys[MAX_KEY_PRESSES]; 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)); + + // Create keyboard state array + 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; + } + + // Check if all keys result in text, if not -> is potential hotkey -> shouldn't output any text + for (int32 key_state = 0; key_state < MAX_KEY_PRESS_TYPES; ++key_state) { + if ((input->general_states & INPUT_STATE_GENERAL_TYPING_MODE) + && (state->active_keys[key_state].scan_code & INPUT_KEYBOARD_PREFIX) + && state->active_keys[key_state].key_state != KEY_PRESS_TYPE_RELEASED + ) { + if (input_characters >= ARRAY_COUNT(input->characters)) { + break; + } + + uint32 code = key_to_unicode( + state->active_keys[key_state].scan_code & 0x00FF, + 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; + } + + input->characters[input_characters++] = code; + } + } + + if (input_characters) { + for (int32 key_state = 0; key_state < MAX_KEY_PRESS_TYPES; ++key_state) { + state->active_keys[key_state].is_processed = true; + state->active_keys[key_state].time = 0; // @todo fix + } + + input_clean_state(state->active_keys); + return; + } + } int32 active_hotkeys = 0; - // Check every key down state - for (int key_state = 0; key_state < MAX_KEY_STATES; ++key_state) { - if (state->state_keys[key_state].key_id == 0 - || state->state_keys[key_state].key_state == KEY_STATE_RELEASED - ) { - // no key defined for this down state - continue; - } + // Check every mapping + for (int32 i = 0; i < 2; ++i) { + InputMapping* mapping = i == 0 ? &input->input_mapping1 : &input->input_mapping2; - // Is a key defined for this state AND is at least one hotkey defined for this key - // 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); + // 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; + } - // Handle 2 input devices (1 = keyboard + mouse, 2 = controller) - // @performance Could it make sense to only loop over one mapping (create a pointer that references the correct mapping) - // We then swap this pointer whenever we detect a input from keyboard+mouse vs controller - // This would allow us even to add context specific mappings - for (int32 i = 0; i < 2; ++i) { - InputMapping* mapping; - if (i == 0) { - mapping = &input->input_mapping1; - } else if ((input->handle_controller || input->direct_controller) - && key->key_id > INPUT_CONTROLLER_PREFIX + if (hotkey_is_active(state->active_hotkeys, hotkey_idx), + !hotkey_keys_are_active(state->active_keys, mapping, hotkey_idx) ) { - mapping = &input->input_mapping2; - } else { + // 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; } - if (mapping->keys[(internal_key_id - 1) * MAX_KEY_TO_HOTKEY] == 0) { - // no possible hotkey associated with this key - continue; - } + state->active_hotkeys[active_hotkeys++] = hotkey_idx; - const uint8* hotkeys_for_key = mapping->keys + (internal_key_id - 1) * MAX_KEY_TO_HOTKEY; - - // Check every possible hotkey - // Since multiple input devices have their own button/key indices whe have to do this weird range handling - for (int32 possible_hotkey_idx = 0; possible_hotkey_idx < MAX_KEY_TO_HOTKEY; ++possible_hotkey_idx) { - // We only support a slimited amount of active hotkeys - if (active_hotkeys >= MAX_KEY_PRESSES) { - return; - } - - // Hotkey already active - // @question Do we even need this? This shouldn't happen anyway?! - if (hotkey_is_active(state->state_hotkeys, hotkeys_for_key[possible_hotkey_idx])) { - continue; - } - - // store active hotkey, if it is not already active - 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 - if (input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]] != 0 - && old_hotkeys[0] != hotkeys_for_key[possible_hotkey_idx] - && 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); - } + // Run callback if defined + if (mapping->hotkeys[hotkey_idx].callback != 0) { + mapping->hotkeys[hotkey_idx].callback(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 // 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 @@ -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 } -bool input_key_is_longpress(InputState* state, uint16 key, uint64 time, f32 dt = 0.0f) { - for (int32 i = 0; i < MAX_KEY_STATES; ++i) { - if (state->state_keys[i].key_id == key) { - return (f32) (time - state->state_keys[i].time) / 1000.0f >= (dt == 0.0f ? INPUT_LONG_PRESS_DURATION : dt); +// @todo We probably need a way to unset a specific key and hotkey after processing it +bool input_key_is_longpress(const InputState* state, int16 key, uint64 time, f32 dt = 0.0f) { + for (int32 i = 0; i < MAX_KEY_PRESS_TYPES; ++i) { + 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! -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; for (int32 i = 0; i < MAX_KEY_PRESSES; ++i) { - if (input->state.state_hotkeys[i] != hotkey) { + if (input->state.active_hotkeys[i] != hotkey) { 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) { bool potential_miss = true; bool both_empty = false; - if (input->input_mapping1.hotkeys[hotkey * MAX_HOTKEY_COMBINATION + j] > 0) { - if(!input_key_is_longpress(&input->state, input->input_mapping1.hotkeys[hotkey + j], time, dt)) { + if (input->input_mapping1.hotkeys[hotkey].scan_codes[j] > 0) { + if(!input_key_is_longpress(&input->state, input->input_mapping1.hotkeys[hotkey].scan_codes[j], time, dt)) { potential_miss = true; } else { potential_miss = false; @@ -676,8 +657,8 @@ bool input_hotkey_is_longpress(Input* input, uint8 hotkey, uint64 time, f32 dt = continue; } - if (input->input_mapping2.hotkeys[hotkey * MAX_HOTKEY_COMBINATION + j] > 0) { - if(!input_key_is_longpress(&input->state, input->input_mapping2.hotkeys[hotkey + j], time, dt)) { + if (input->input_mapping2.hotkeys[hotkey].scan_codes[j] > 0) { + if(!input_key_is_longpress(&input->state, input->input_mapping2.hotkeys[hotkey].scan_codes[j], time, dt)) { potential_miss = true; } else { potential_miss = false; @@ -697,4 +678,48 @@ bool input_hotkey_is_longpress(Input* input, uint8 hotkey, uint64 time, f32 dt = 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 \ No newline at end of file diff --git a/log/Debug.cpp b/log/Debug.cpp index ba66bdb..e19bcaf 100644 --- a/log/Debug.cpp +++ b/log/Debug.cpp @@ -8,7 +8,6 @@ #include "TimingStat.h" #include "../utils/StringUtils.h" #include "../utils/TestUtils.h" -#include "../utils/MathUtils.h" #include "../thread/Atomic.h" // Required for rdtsc(); @@ -69,34 +68,24 @@ void log_to_file() #if _WIN32 DWORD written; - if (!WriteFile( + WriteFile( debug_container->log_fp, (char *) debug_container->log_memory.memory, - (uint32) debug_container->log_memory.pos - 1, + (uint32) debug_container->log_memory.pos, &written, NULL - )) { - CloseHandle(debug_container->log_fp); - } + ); #else if (debug_container->log_fp < 0) { return; } - if (!write( + write( debug_container->log_fp, (char *) debug_container->log_memory.memory, - (uint32) debug_container->log_memory.pos - 1 - )) { - close(debug_container->log_fp); - } + (uint32) debug_container->log_memory.pos + ); #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 @@ -184,9 +173,8 @@ void log_counter(int32 id, int64 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 -DebugMemory* debug_memory_find(uint64 start) +DebugMemory* debug_memory_find(uintptr_t start) { for (uint64 i = 0; i < debug_container->dmc.memory_size; ++i) { if (debug_container->dmc.memory_stats[i].start <= start @@ -199,7 +187,7 @@ DebugMemory* debug_memory_find(uint64 start) return NULL; } -void debug_memory_init(uint64 start, uint64 size) +void debug_memory_init(uintptr_t start, uint64 size) { if (!start || !debug_container) { return; @@ -231,7 +219,7 @@ void debug_memory_init(uint64 start, uint64 size) ++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) { 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) { return; @@ -290,7 +278,7 @@ void debug_memory_reserve(uint64 start, uint64 size, int32 type, const char* fun } // undo reserve -void debug_memory_free(uint64 start, uint64 size) +void debug_memory_free(uintptr_t start, uint64 size) { if (!start || !debug_container) { return; @@ -331,124 +319,118 @@ void debug_memory_reset() } // @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; - ASSERT_SIMPLE(size <= 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) { + if (log_mem->pos + MAX_LOG_LENGTH > log_mem->size) { 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); - if (zeroed) { - memset((void *) offset, 0, size); - } + memset((void *) offset, 0, MAX_LOG_LENGTH); - log_mem->pos += size; + log_mem->pos += MAX_LOG_LENGTH; return offset; } -// @todo add file name, function name and function line -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) { if (!should_log || !debug_container) { return; } - size_t str_len = OMS_MIN(strlen(str), MAX_LOG_LENGTH - 128); - size_t file_len = strlen(file); - size_t function_len = strlen(function); + int64 len = strlen(str); + while (len > 0) { + LogMessage* msg = (LogMessage *) log_get_memory(); - char line_str[14]; - uint_to_str(line, line_str); + // Fill file + 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); - 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(); + if (debug_container->log_memory.size - debug_container->log_memory.pos < MAX_LOG_LENGTH) { + 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) { return; } - if (data_type == LOG_DATA_VOID) { - log(format, should_log, save, file, function, line); + if (data.data[0].type == LOG_DATA_VOID) { + 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) { - case LOG_DATA_INT32: { - sprintf(temp, format, *((int32 *) data)); - } break; - case LOG_DATA_UINT32: { - sprintf(temp, format, *((uint32 *) data)); - } break; - case LOG_DATA_INT64: { - sprintf(temp, format, *((int64 *) data)); - } break; - case LOG_DATA_UINT64: { - sprintf(temp, format, *((uint64 *) data)); - } break; - case LOG_DATA_CHAR: { - sprintf(temp, format, *((char *) data)); - } break; - case LOG_DATA_CHAR_STR: { - sprintf(temp, format, *((char *) data)); - } break; - case LOG_DATA_FLOAT32: { - sprintf(temp, format, *((f32 *) data)); - } break; - case LOG_DATA_FLOAT64: { - sprintf(temp, format, *((f64 *) data)); - } break; - default: { - UNREACHABLE(); + 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: { + sprintf_fast_iter(msg->message, temp_format, *((int32 *) data.data[i].value)); + } break; + case LOG_DATA_UINT32: { + sprintf_fast_iter(msg->message, temp_format, *((uint32 *) data.data[i].value)); + } break; + case LOG_DATA_INT64: { + sprintf_fast_iter(msg->message, temp_format, *((int64 *) data.data[i].value)); + } break; + case LOG_DATA_UINT64: { + sprintf_fast_iter(msg->message, temp_format, *((uint64 *) data.data[i].value)); + } break; + case LOG_DATA_CHAR: { + sprintf_fast_iter(msg->message, temp_format, *((char *) data.data[i].value)); + } break; + case LOG_DATA_CHAR_STR: { + sprintf_fast_iter(msg->message, temp_format, (const char *) data.data[i].value); + } break; + case LOG_DATA_FLOAT32: { + sprintf_fast_iter(msg->message, temp_format, *((f32 *) data.data[i].value)); + } break; + case LOG_DATA_FLOAT64: { + sprintf_fast_iter(msg->message, temp_format, *((f64 *) data.data[i].value)); + } break; + default: { + 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(); + debug_container->log_memory.pos = 0; } - - ASSERT_SIMPLE(false); } - #endif \ No newline at end of file diff --git a/log/Debug.h b/log/Debug.h index 0cb1aee..79ef15a 100644 --- a/log/Debug.h +++ b/log/Debug.h @@ -18,15 +18,56 @@ #include #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 { byte* memory; - uint32 id; uint64 size; 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 { diff --git a/log/DebugMemory.h b/log/DebugMemory.h index 1e53b16..be0f298 100644 --- a/log/DebugMemory.h +++ b/log/DebugMemory.h @@ -16,7 +16,7 @@ struct DebugMemoryRange { int32 type; - uint64 start; + uintptr_t start; uint64 size; uint64 time; @@ -25,7 +25,7 @@ struct DebugMemoryRange { struct DebugMemory { uint64 usage; - uint64 start; + uintptr_t start; uint64 size; uint64 action_idx; @@ -42,10 +42,10 @@ struct DebugMemoryContainer { }; #if DEBUG || INTERNAL - void debug_memory_init(uint64, uint64); - void debug_memory_log(uint64, uint64, int32, const char*); - void debug_memory_reserve(uint64, uint64, int32, const char*); - void debug_memory_free(uint64, uint64); + void debug_memory_init(uintptr_t, uint64); + void debug_memory_log(uintptr_t, uint64, int32, const char*); + void debug_memory_reserve(uintptr_t, uint64, int32, const char*); + void debug_memory_free(uintptr_t, uint64); void debug_memory_reset(); #define DEBUG_MEMORY_INIT(start, size) debug_memory_init((start), (size)) diff --git a/log/Log.h b/log/Log.h index d19e3d9..6866fdf 100644 --- a/log/Log.h +++ b/log/Log.h @@ -13,63 +13,37 @@ #include "../stdlib/Types.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(const char* str, bool should_log, bool save, 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* str, bool should_log, 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_counter(int32, int64); -#define LOG_PERFORMANCE_START(time_start) \ -({ \ - time_start = __rdtsc(); \ -}) +#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__) +#define LOG_TO_FILE() log_to_file() -#define LOG_PERFORMANCE_END(time_start) \ -({ \ - printf("%ld\n", __rdtsc() - (time_start)); \ -}) +#if LOG_LEVEL == 2 + #define LOG_LEVEL_1(format, ...) log((format), LogDataArray{__VA_ARGS__}, true, __FILE__, __func__, __LINE__) + #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 - // 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_BY(a, b) ((void) 0) #define LOG_COUNTER(a, b) ((void) 0) #define RESET_COUNTER(a) ((void) 0) #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_BY(a, b) log_increment((a), (b)) #define LOG_COUNTER(a, b) log_counter((a), (b)) #define RESET_COUNTER(a) reset_counter((a)) #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 \ No newline at end of file diff --git a/math/matrix/MatrixFloat32.h b/math/matrix/MatrixFloat32.h index 267d8d6..eda2a07 100644 --- a/math/matrix/MatrixFloat32.h +++ b/math/matrix/MatrixFloat32.h @@ -12,7 +12,6 @@ #include #include #include -#include "../../utils/MathUtils.h" #include "../../utils/TestUtils.h" #if ARM @@ -345,7 +344,7 @@ void mat4_identity(__m128* matrix) // https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula 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 f32 s = sinf(angle); diff --git a/math/matrix/MatrixInt32.h b/math/matrix/MatrixInt32.h index 78d9662..13712b3 100644 --- a/math/matrix/MatrixInt32.h +++ b/math/matrix/MatrixInt32.h @@ -9,8 +9,6 @@ #ifndef TOS_MATH_MATRIX_INT32_H #define TOS_MATH_MATRIX_INT32_H -#include "../../utils/MathUtils.h" - #if ARM #include "../../stdlib/IntrinsicsArm.h" #else diff --git a/math/matrix/MatrixInt64.h b/math/matrix/MatrixInt64.h index e983447..397c6eb 100644 --- a/math/matrix/MatrixInt64.h +++ b/math/matrix/MatrixInt64.h @@ -9,8 +9,6 @@ #ifndef TOS_MATH_MATRIX_INT64_H #define TOS_MATH_MATRIX_INT64_H -#include "../../utils/MathUtils.h" - #if ARM #include "../../stdlib/IntrinsicsArm.h" #else diff --git a/math/matrix/QuaternionFloat32.h b/math/matrix/QuaternionFloat32.h index 92257ae..9b89d03 100644 --- a/math/matrix/QuaternionFloat32.h +++ b/math/matrix/QuaternionFloat32.h @@ -10,7 +10,6 @@ #ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H #define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H -#include "../../utils/MathUtils.h" #include "../../utils/TestUtils.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); // 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->roll = 0.0f; } else { @@ -225,7 +224,7 @@ void quaternion_rotate_vector(v3_f32* __restrict vec, const v4_f32* __restrict q inline 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; 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 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; quaternion_multiply(&p_tmp, quat, p); diff --git a/math/matrix/VectorFloat32.h b/math/matrix/VectorFloat32.h index ee0b541..83f91ce 100644 --- a/math/matrix/VectorFloat32.h +++ b/math/matrix/VectorFloat32.h @@ -9,7 +9,6 @@ #ifndef TOS_MATH_MATRIX_VECTOR_FLOAT32_H #define TOS_MATH_MATRIX_VECTOR_FLOAT32_H -#include "../../utils/MathUtils.h" #include "../../stdlib/Simd.h" struct v3_f32_4 { diff --git a/math/matrix/VectorFloat64.h b/math/matrix/VectorFloat64.h index 47bfab1..abee9e1 100644 --- a/math/matrix/VectorFloat64.h +++ b/math/matrix/VectorFloat64.h @@ -9,7 +9,6 @@ #ifndef TOS_MATH_MATRIX_VECTOR_FLOAT64_H #define TOS_MATH_MATRIX_VECTOR_FLOAT64_H -#include "../../utils/MathUtils.h" #include "../../stdlib/Simd.h" #endif \ No newline at end of file diff --git a/math/matrix/VectorInt32.h b/math/matrix/VectorInt32.h index 1ed4da2..8f82cb1 100644 --- a/math/matrix/VectorInt32.h +++ b/math/matrix/VectorInt32.h @@ -12,7 +12,6 @@ #include #include -#include "../../utils/MathUtils.h" #include "../../stdlib/Simd.h" struct v3_int32_4 { diff --git a/math/matrix/VectorInt64.h b/math/matrix/VectorInt64.h index acaff72..a279cc1 100644 --- a/math/matrix/VectorInt64.h +++ b/math/matrix/VectorInt64.h @@ -12,7 +12,6 @@ #include #include -#include "../../utils/MathUtils.h" #include "../../stdlib/Simd.h" struct v3_int64_2 { diff --git a/memory/BufferMemory.h b/memory/BufferMemory.h index 6af17ff..e560fb7 100644 --- a/memory/BufferMemory.h +++ b/memory/BufferMemory.h @@ -11,7 +11,6 @@ #include #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" #include "../utils/EndianUtils.h" #include "../utils/TestUtils.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); - 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 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) { platform_free((void **) &buf->memory); } else { @@ -74,15 +75,15 @@ void buffer_init(BufferMemory* buf, byte* data, uint64 size, int32 alignment = 6 buf->alignment = alignment; buf->element_alignment = 0; - DEBUG_MEMORY_INIT((uint64) buf->memory, buf->size); - DEBUG_MEMORY_RESERVE((uint64) buf->memory, buf->size, 187); + DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size); + DEBUG_MEMORY_RESERVE((uintptr_t) buf->memory, buf->size, 187); } inline void buffer_reset(BufferMemory* buf) { // @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; } @@ -107,7 +108,7 @@ byte* buffer_get_memory(BufferMemory* buf, uint64 size, int32 aligned = 4, bool 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; buf->head += size; diff --git a/memory/ChunkMemory.h b/memory/ChunkMemory.h index 45bf43e..fd0ea05 100644 --- a/memory/ChunkMemory.h +++ b/memory/ChunkMemory.h @@ -11,7 +11,6 @@ #include #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" #include "../utils/TestUtils.h" #include "../utils/EndianUtils.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); - 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 @@ -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 buf->free = (uint64 *) (buf->memory + count * chunk_size); - DEBUG_MEMORY_INIT((uint64) buf->memory, buf->size); - DEBUG_MEMORY_RESERVE((uint64) buf->memory, buf->size, 187); + DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size); + DEBUG_MEMORY_RESERVE((uintptr_t) buf->memory, buf->size, 187); } 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 buf->free = (uint64 *) (buf->memory + count * chunk_size); - DEBUG_MEMORY_INIT((uint64) buf->memory, buf->size); - DEBUG_MEMORY_RESERVE((uint64) buf->memory, buf->size, 187); + DEBUG_MEMORY_INIT((uintptr_t) buf->memory, buf->size); + DEBUG_MEMORY_RESERVE((uintptr_t) buf->memory, buf->size, 187); } inline 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) { platform_free((void **) &buf->memory); } else { @@ -138,7 +139,7 @@ byte* chunk_get_element(ChunkMemory* buf, uint64 element, bool zeroed = false) 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; } @@ -246,7 +247,7 @@ int32 chunk_reserve(ChunkMemory* buf, uint32 elements = 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; @@ -256,14 +257,14 @@ int32 chunk_reserve(ChunkMemory* buf, uint32 elements = 1) inline 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); } inline 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; 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); + LOG_LEVEL_2("Loaded ChunkMemory: %n B", {{LOG_DATA_UINT64, &buf->size}}); + return buf->size; } diff --git a/memory/Heap.h b/memory/Heap.h index 7d37c95..4c5a7eb 100644 --- a/memory/Heap.h +++ b/memory/Heap.h @@ -39,12 +39,12 @@ void heap_alloc(Heap* heap, uint32 element_size, uint64 capacity, int32 (*compar heap->compare = compare; 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) { - 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); } @@ -61,7 +61,7 @@ void heap_init(Heap* heap, BufferMemory* buf, uint32 element_size, uint64 capaci heap->size = 0; 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) { @@ -127,7 +127,7 @@ void heap_pop(Heap* heap, void* out) { 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); void* last_element = heap->elements + ((heap->size - 1) * heap->element_size); @@ -138,7 +138,7 @@ void heap_pop(Heap* heap, void* out) { inline 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; } diff --git a/memory/RingMemory.h b/memory/RingMemory.h index 15527a7..49a53eb 100644 --- a/memory/RingMemory.h +++ b/memory/RingMemory.h @@ -13,7 +13,6 @@ #include #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" #include "../utils/EndianUtils.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); - 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 @@ -75,8 +76,8 @@ void ring_init(RingMemory* ring, BufferMemory* buf, uint64 size, uint32 alignmen ring->size = size; ring->alignment = alignment; - DEBUG_MEMORY_INIT((uint64) ring->memory, ring->size); - DEBUG_MEMORY_RESERVE((uint64) ring->memory, ring->size, 187); + DEBUG_MEMORY_INIT((uintptr_t) ring->memory, ring->size); + DEBUG_MEMORY_RESERVE((uintptr_t) ring->memory, ring->size, 187); } inline @@ -94,8 +95,8 @@ void ring_init(RingMemory* ring, byte* buf, uint64 size, uint32 alignment = 64) memset(ring->memory, 0, ring->size); - DEBUG_MEMORY_INIT((uint64) ring->memory, ring->size); - DEBUG_MEMORY_RESERVE((uint64) ring->memory, ring->size, 187); + DEBUG_MEMORY_INIT((uintptr_t) ring->memory, ring->size); + DEBUG_MEMORY_RESERVE((uintptr_t) ring->memory, ring->size, 187); } inline @@ -134,7 +135,7 @@ byte* ring_calculate_position(const RingMemory* ring, uint64 size, uint32 aligne inline 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; } @@ -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. // 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) { 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); } - DEBUG_MEMORY_WRITE((uint64) ring->head, size); + DEBUG_MEMORY_WRITE((uintptr_t) ring->head, size); byte* offset = ring->head; ring->head += size; @@ -224,7 +225,7 @@ byte* ring_get_memory_nomove(RingMemory* ring, uint64 size, uint32 aligned = 4, memset((void *) pos, 0, size); } - DEBUG_MEMORY_WRITE((uint64) pos, size); + DEBUG_MEMORY_WRITE((uintptr_t) pos, size); return pos; } @@ -236,7 +237,7 @@ byte* ring_get_element(const RingMemory* ring, uint64 element_count, uint64 elem { 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; } diff --git a/models/mob/Mob.cpp b/models/mob/Mob.cpp index aa3005a..5404d43 100644 --- a/models/mob/Mob.cpp +++ b/models/mob/Mob.cpp @@ -9,7 +9,6 @@ #ifndef TOS_MODELS_MOB_C #define TOS_MODELS_MOB_C -#include "../../utils/MathUtils.h" #include "Mob.h" #include "MobState.h" diff --git a/models/mob/monster/LootTable.h b/models/mob/monster/LootTable.h index 7d3df4a..d9c0900 100644 --- a/models/mob/monster/LootTable.h +++ b/models/mob/monster/LootTable.h @@ -11,7 +11,6 @@ #include "../../../stdlib/Types.h" #include "../../../utils/Utils.h" -#include "../../../utils/MathUtils.h" #include "Drop.h" // @todo how to do class specific loot table? diff --git a/pathfinding/Jpsp.h b/pathfinding/Jpsp.h index 82ddc68..1ff59ed 100644 --- a/pathfinding/Jpsp.h +++ b/pathfinding/Jpsp.h @@ -14,7 +14,6 @@ #include #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" struct JPSNode { int32 x, y; diff --git a/pathfinding/Metric2d.h b/pathfinding/Metric2d.h index 255cd9d..f3f05f8 100644 --- a/pathfinding/Metric2d.h +++ b/pathfinding/Metric2d.h @@ -14,7 +14,6 @@ #include #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" f32 manhattan_2d(v2_f32 a, v2_f32 b) { return fabs(a.x - b.x) + fabs(a.y - b.y); diff --git a/pathfinding/Path.h b/pathfinding/Path.h index 86d6fe3..32807a4 100644 --- a/pathfinding/Path.h +++ b/pathfinding/Path.h @@ -14,7 +14,6 @@ #include #include "../stdlib/Types.h" -#include "../utils/MathUtils.h" struct Path { diff --git a/pathfinding/jps/Jps.h b/pathfinding/jps/Jps.h index 8d13db2..1a047f1 100644 --- a/pathfinding/jps/Jps.h +++ b/pathfinding/jps/Jps.h @@ -14,7 +14,6 @@ #include #include "../../stdlib/Types.h" -#include "../../utils/MathUtils.h" #include "JpsGrid.h" #include "../Path.h" diff --git a/pathfinding/jps/JpsGrid.h b/pathfinding/jps/JpsGrid.h index 47480e5..01968eb 100644 --- a/pathfinding/jps/JpsGrid.h +++ b/pathfinding/jps/JpsGrid.h @@ -14,7 +14,6 @@ #include #include "../../stdlib/Types.h" -#include "../../utils/MathUtils.h" #include "JpsNode.h" diff --git a/pathfinding/jps/JpsNode.h b/pathfinding/jps/JpsNode.h index c9a9964..308ea96 100644 --- a/pathfinding/jps/JpsNode.h +++ b/pathfinding/jps/JpsNode.h @@ -14,7 +14,6 @@ #include #include "../../stdlib/Types.h" -#include "../../utils/MathUtils.h" struct JpsNode { bool is_walkable; diff --git a/platform/win32/Allocator.h b/platform/win32/Allocator.h index ab4a5f6..632098a 100644 --- a/platform/win32/Allocator.h +++ b/platform/win32/Allocator.h @@ -15,6 +15,7 @@ #include "../../utils/TestUtils.h" // @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 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); } -// @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 void* platform_alloc_aligned(size_t size, int32 alignment) { diff --git a/platform/win32/SystemInfo.cpp b/platform/win32/SystemInfo.cpp index 8b6df42..7c01857 100644 --- a/platform/win32/SystemInfo.cpp +++ b/platform/win32/SystemInfo.cpp @@ -276,6 +276,7 @@ int network_info_get(NetworkInfo* info) { // Get the size of the adapter addresses buffer if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) { + // @todo Remove malloc pAdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(dwSize); if (pAdapterAddresses == NULL) { WSACleanup(); diff --git a/platform/win32/UtilsWin32.h b/platform/win32/UtilsWin32.h index 845897b..e2da56c 100644 --- a/platform/win32/UtilsWin32.h +++ b/platform/win32/UtilsWin32.h @@ -9,10 +9,27 @@ #ifndef TOS_PLATFORM_WIN32_UTILS_H #define TOS_PLATFORM_WIN32_UTILS_H +#include "../../stdlib/Types.h" #include #include #include #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 \ No newline at end of file diff --git a/platform/win32/Window.h b/platform/win32/Window.h index e06628f..71fefe9 100644 --- a/platform/win32/Window.h +++ b/platform/win32/Window.h @@ -28,6 +28,7 @@ struct Window { // 3. size // 4. fullscreen byte state_changes; + // @todo replace bools with states bool is_focused; 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? HGLRC openGLRC; + // @question why do we need the name? char name[32]; WindowState state_old; }; diff --git a/platform/win32/audio/DirectSound.h b/platform/win32/audio/DirectSound.h index 762cdb5..2fcf85c 100644 --- a/platform/win32/audio/DirectSound.h +++ b/platform/win32/audio/DirectSound.h @@ -15,7 +15,6 @@ #include "../../../stdlib/Types.h" #include "../../../audio/AudioSetting.h" -#include "../../../utils/MathUtils.h" #include "../../../log/Log.h" #include "../../../audio/Audio.cpp" @@ -35,7 +34,7 @@ HRESULT WINAPI DirectSoundCreate8Stub(LPCGUID, LPDIRECTSOUND8*, LPUNKNOWN) { void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_setting) { HMODULE lib = LoadLibraryExA((LPCSTR) "dsound.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (!lib) { - LOG("DirectSound: Couldn't load dsound.dll\n", true, true); + LOG(true, "DirectSound: Couldn't load dsound.dll\n"); return; } @@ -43,13 +42,13 @@ void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_settin DirectSoundCreate8_t* DirectSoundCreate8 = (DirectSoundCreate8_t *) GetProcAddress(lib, "DirectSoundCreate8"); if (!DirectSoundCreate8 || !SUCCEEDED(DirectSoundCreate8(0, &api_setting->audio_handle, 0))) { - LOG("DirectSound: DirectSoundCreate8 failed\n", true, true); + LOG(true, "DirectSound: DirectSoundCreate8 failed\n"); return; } if(!SUCCEEDED(api_setting->audio_handle->SetCooperativeLevel(hwnd, DSSCL_PRIORITY))) { - LOG("DirectSound: SetCooperativeLevel failed.\n", true, true); + LOG(true, "DirectSound: SetCooperativeLevel failed.\n"); return; } @@ -71,13 +70,13 @@ void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_settin buffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER; 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; } if (!SUCCEEDED(api_setting->primary_buffer->SetFormat(&wf))) { - LOG("DirectSound: SetFormat failed.\n", true, true); + LOG(true, "DirectSound: SetFormat failed.\n"); return; } @@ -93,7 +92,7 @@ void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_settin buffer_desc2.lpwfxFormat = &wf; 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; } @@ -143,7 +142,7 @@ uint32 audio_buffer_fillable(const AudioSetting* setting, const DirectSoundSetti DWORD player_cursor; DWORD 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; } diff --git a/platform/win32/audio/Wasapi.h b/platform/win32/audio/Wasapi.h index cfbde9d..305623c 100644 --- a/platform/win32/audio/Wasapi.h +++ b/platform/win32/audio/Wasapi.h @@ -18,7 +18,6 @@ #include "../../../stdlib/Types.h" #include "../../../audio/AudioSetting.h" -#include "../../../utils/MathUtils.h" #include "../../../log/Log.h" #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) { HMODULE ole32 = LoadLibraryExA((LPCSTR) "ole32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (!ole32) { - LOG("Wasapi: Couldn't load ole32.dll\n", true, true); + LOG(true, "Wasapi: Couldn't load ole32.dll\n"); 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"); 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; } HMODULE mmdevapi = LoadLibraryExA((LPCSTR) "mmdevapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (!mmdevapi) { - LOG("Wasapi: Couldn't load mmdevapi.dll\n", true, true); + LOG(true, "Wasapi: Couldn't load mmdevapi.dll\n"); 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"); if (!IMMDeviceEnumerator_GetDefaultAudioEndpoint || !IMMDevice_Activate) { - LOG("Wasapi: mmdevapi function binding failed\n", true, true); + LOG(true, "Wasapi: mmdevapi function binding failed\n"); return; } HMODULE audioclient = LoadLibraryExA((LPCSTR) "audioclient.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (!audioclient) { - LOG("Wasapi: Couldn't load audioclient.dll\n", true, true); + LOG(true, "Wasapi: Couldn't load audioclient.dll\n"); 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"); 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; } HRESULT hr = co_initialize_ex(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) { - LOG("Wasapi: Wasapi initialize failed\n", true, true); + LOG(true, "Wasapi: Wasapi initialize failed\n"); 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); if (FAILED(hr)) { - LOG("Wasapi: Wasapi CreateInstance failed\n", true, true); + LOG(true, "Wasapi: Wasapi CreateInstance failed\n"); return; } hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eConsole, &device); if (FAILED(hr)) { - LOG("Wasapi: Wasapi DefaultAudioEndpoint failed\n", true, true); + LOG(true, "Wasapi: Wasapi DefaultAudioEndpoint failed\n"); 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); if (FAILED(hr)) { - LOG("Wasapi: Wasapi DeviceActivate failed\n", true, true); + LOG(true, "Wasapi: Wasapi DeviceActivate failed\n"); device->Release(); enumerator->Release(); diff --git a/platform/win32/audio/XAudio2.h b/platform/win32/audio/XAudio2.h index 6cf3b31..dbd1b20 100644 --- a/platform/win32/audio/XAudio2.h +++ b/platform/win32/audio/XAudio2.h @@ -37,20 +37,20 @@ void audio_load(HWND hwnd, AudioSetting* setting, XAudio2Setting* api_setting) { CoInitialize(NULL); HMODULE lib = LoadLibraryExA((LPCSTR) "xaudio2_9.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); 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); } if (!lib) { - LOG("Xaudio2: Couldn't load xaudio2_8.dll\n", true, true); + LOG(true, "Xaudio2: Couldn't load xaudio2_8.dll\n"); return; } XAudio2Create_t* XAudio2Create = (XAudio2Create_t *) GetProcAddress(lib, "XAudio2Create"); 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; } @@ -63,7 +63,7 @@ void audio_load(HWND hwnd, AudioSetting* setting, XAudio2Setting* api_setting) { 0, NULL)) ) { - LOG("Xaudio2: CreateMasteringVoice failed\n", true, true); + LOG(true, "Xaudio2: CreateMasteringVoice failed\n"); return; } @@ -78,7 +78,7 @@ void audio_load(HWND hwnd, AudioSetting* setting, XAudio2Setting* api_setting) { wf.cbSize = 0; 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; } @@ -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]))) { - LOG("Xaudio2: SubmitSourceBuffer failed\n", true, true); + LOG(true, "Xaudio2: SubmitSourceBuffer failed\n"); return; } diff --git a/platform/win32/input/HidInput.h b/platform/win32/input/HidInput.h index 4a1f2e1..4dfab31 100644 --- a/platform/win32/input/HidInput.h +++ b/platform/win32/input/HidInput.h @@ -155,7 +155,7 @@ uint32 hid_device_poll(Input* state, uint64 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; return 0; diff --git a/platform/win32/input/RawInput.h b/platform/win32/input/RawInput.h index f047b9e..ea36f0c 100644 --- a/platform/win32/input/RawInput.h +++ b/platform/win32/input/RawInput.h @@ -226,44 +226,44 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32 InputKey key; if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) { - key.key_state = KEY_STATE_PRESSED; - key.key_id = INPUT_MOUSE_BUTTON_1; + key.key_state = KEY_PRESS_TYPE_PRESSED; + key.scan_code = INPUT_MOUSE_BUTTON_1; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) { - key.key_state = KEY_STATE_RELEASED; - key.key_id = INPUT_MOUSE_BUTTON_1; + key.key_state = KEY_PRESS_TYPE_RELEASED; + key.scan_code = INPUT_MOUSE_BUTTON_1; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) { - key.key_state = KEY_STATE_PRESSED; - key.key_id = INPUT_MOUSE_BUTTON_2; + key.key_state = KEY_PRESS_TYPE_PRESSED; + key.scan_code = INPUT_MOUSE_BUTTON_2; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) { - key.key_state = KEY_STATE_RELEASED; - key.key_id = INPUT_MOUSE_BUTTON_2; + key.key_state = KEY_PRESS_TYPE_RELEASED; + key.scan_code = INPUT_MOUSE_BUTTON_2; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) { - key.key_state = KEY_STATE_PRESSED; - key.key_id = INPUT_MOUSE_BUTTON_3; + key.key_state = KEY_PRESS_TYPE_PRESSED; + key.scan_code = INPUT_MOUSE_BUTTON_3; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) { - key.key_state = KEY_STATE_RELEASED; - key.key_id = INPUT_MOUSE_BUTTON_3; + key.key_state = KEY_PRESS_TYPE_RELEASED; + key.scan_code = INPUT_MOUSE_BUTTON_3; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) { - key.key_state = KEY_STATE_PRESSED; - key.key_id = INPUT_MOUSE_BUTTON_4; + key.key_state = KEY_PRESS_TYPE_PRESSED; + key.scan_code = INPUT_MOUSE_BUTTON_4; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) { - key.key_state = KEY_STATE_RELEASED; - key.key_id = INPUT_MOUSE_BUTTON_4; + key.key_state = KEY_PRESS_TYPE_RELEASED; + key.scan_code = INPUT_MOUSE_BUTTON_4; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) { - key.key_state = KEY_STATE_PRESSED; - key.key_id = INPUT_MOUSE_BUTTON_5; + key.key_state = KEY_PRESS_TYPE_PRESSED; + key.scan_code = INPUT_MOUSE_BUTTON_5; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) { - key.key_state = KEY_STATE_RELEASED; - key.key_id = INPUT_MOUSE_BUTTON_5; + key.key_state = KEY_PRESS_TYPE_RELEASED; + key.scan_code = INPUT_MOUSE_BUTTON_5; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) { // @bug not working - key.key_state = KEY_STATE_RELEASED; - key.key_id = INPUT_MOUSE_BUTTON_WHEEL; + key.key_state = KEY_PRESS_TYPE_RELEASED; + key.scan_code = INPUT_MOUSE_BUTTON_WHEEL; key.value = (int16) raw->data.mouse.usButtonData; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_HWHEEL) { // @bug not working - key.key_state = KEY_STATE_RELEASED; - key.key_id = INPUT_MOUSE_BUTTON_HWHEEL; + key.key_state = KEY_PRESS_TYPE_RELEASED; + key.scan_code = INPUT_MOUSE_BUTTON_HWHEEL; key.value = (int16) raw->data.mouse.usButtonData; } else { return 0; @@ -271,12 +271,12 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32 ++input_count; - key.key_id |= INPUT_MOUSE_PREFIX; + key.scan_code |= INPUT_MOUSE_PREFIX; key.time = time; - input_set_state(states[i].state.state_keys, &key); - states[i].state_change_button = true; - } else if (states[i].mouse_movement) { + input_set_state(states[i].state.active_keys, &key); + states[i].general_states |= INPUT_STATE_GENERAL_BUTTON_CHANGE; + } 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 if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) { 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.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) { states[i].state.dx += raw->data.mouse.lLastX; 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.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) { @@ -324,21 +324,26 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32 return 0; } - uint16 new_state; + KeyPressType new_state; 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) { - new_state = KEY_STATE_PRESSED; + new_state = KEY_PRESS_TYPE_PRESSED; } else { return 0; } ++input_count; - // @todo change to MakeCode instead of VKey - InputKey key = {(uint16) (raw->data.keyboard.VKey | INPUT_KEYBOARD_PREFIX), new_state, 0, time}; - input_set_state(states[i].state.state_keys, &key); - states[i].state_change_button = true; + // @todo we need to support vkey and MakeCode/ScanCode for input mode -> typing and recognizing the respective unicode + InputKey key = { + (uint16) (raw->data.keyboard.MakeCode | INPUT_KEYBOARD_PREFIX), + (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 && 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); - states[i].state_change_button = true; + states[i].general_states |= INPUT_STATE_GENERAL_BUTTON_CHANGE; states[i].time_last_input_check = time; } diff --git a/platform/win32/input/XInput.h b/platform/win32/input/XInput.h index 0fb449a..bf7c011 100644 --- a/platform/win32/input/XInput.h +++ b/platform/win32/input/XInput.h @@ -14,7 +14,6 @@ #include "../../../input/ControllerInput.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 diff --git a/platform/win32/input/controller/DualSense.h b/platform/win32/input/controller/DualSense.h index 7a10d12..f1cc39a 100644 --- a/platform/win32/input/controller/DualSense.h +++ b/platform/win32/input/controller/DualSense.h @@ -14,7 +14,6 @@ #include "../../../../input/ControllerInput.h" #include "../../../../input/InputConnectionType.h" #include "../../../../utils/BitUtils.h" -#include "../../../../utils/MathUtils.h" // @bug bluetooth and USB have different formats?! // https://github.com/nondebug/dualsense diff --git a/platform/win32/input/controller/DualShock4.h b/platform/win32/input/controller/DualShock4.h index c2d1a7f..6a35523 100644 --- a/platform/win32/input/controller/DualShock4.h +++ b/platform/win32/input/controller/DualShock4.h @@ -14,7 +14,6 @@ #include "../../../../input/ControllerInput.h" #include "../../../../input/InputConnectionType.h" #include "../../../../utils/BitUtils.h" -#include "../../../../utils/MathUtils.h" inline void input_map_dualshock4(ControllerInput* controller, InputConnectionType connection_type, byte* data) diff --git a/platform/win32/threading/Atomic.h b/platform/win32/threading/Atomic.h index 21d2df1..0f89740 100644 --- a/platform/win32/threading/Atomic.h +++ b/platform/win32/threading/Atomic.h @@ -351,7 +351,7 @@ void atomic_and_relaxed(volatile uint64* value, uint64 mask) inline void atomic_and_relaxed(volatile int64* value, int64 mask) { - InterlockedAnd64NoFence((volatile LONG64 *) value, mask); + InterlockedAnd64NoFence((volatile LONG64 *) value, (LONG64) mask); } inline @@ -456,7 +456,7 @@ int32 atomic_get_acquire(volatile int32* value) inline int64 atomic_get_acquire(volatile int64* value) { - return (int64) InterlockedCompareExchangeAcquire((long *) value, 0, 0); + return (int64) InterlockedCompareExchangeAcquire64((LONG64 *) value, 0, 0); } inline @@ -492,13 +492,13 @@ void atomic_decrement_acquire(volatile int32* value) inline void atomic_increment_acquire(volatile int64* value) { - InterlockedIncrementAcquire((long *) value); + InterlockedIncrementAcquire64((LONG64 *) value); } inline void atomic_decrement_acquire(volatile int64* value) { - InterlockedDecrementAcquire((long *) value); + InterlockedDecrementAcquire64((LONG64 *) value); } inline @@ -516,13 +516,13 @@ void atomic_sub_acquire(volatile int32* value, int32 decrement) inline void atomic_add_acquire(volatile int64* value, int64 increment) { - InterlockedAddAcquire((long *) value, (long) increment); + InterlockedAddAcquire64((LONG64 *) value, (LONG64) increment); } inline void atomic_sub_acquire(volatile int64* value, int64 decrement) { - InterlockedAddAcquire((long *) value, -1 * ((long) decrement)); + InterlockedAddAcquire64((LONG64 *) value, -1 * ((LONG64) decrement)); } inline @@ -819,7 +819,7 @@ int32 atomic_get_release(volatile int32* value) inline int64 atomic_get_release(volatile int64* value) { - return (int64) InterlockedCompareExchangeRelease((long *) value, 0, 0); + return (int64) InterlockedCompareExchangeRelease64((LONG64 *) value, 0, 0); } inline @@ -1314,7 +1314,7 @@ void atomic_set_acquire_release(volatile uint32* value, uint32 new_value) inline void atomic_set_acquire_release(volatile uint64* value, uint64 new_value) { - InterlockedExchange((long *) value, (long) new_value); + InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } inline diff --git a/stdlib/HashMap.h b/stdlib/HashMap.h index a70d165..3407cb5 100644 --- a/stdlib/HashMap.h +++ b/stdlib/HashMap.h @@ -140,6 +140,8 @@ void hashmap_create(HashMap* hm, int32 count, int32 element_size, RingMemory* ri hm->table = (void **) data; 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 @@ -153,6 +155,8 @@ void hashmap_create(HashMap* hm, int32 count, int32 element_size, BufferMemory* hm->table = (void **) data; 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 @@ -160,6 +164,8 @@ void hashmap_create(HashMap* hm, int32 count, int32 element_size, byte* buf) { hm->table = (void **) buf; 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 @@ -399,7 +405,7 @@ HashEntry* hashmap_get_reserve(HashMap* hm, const char* key) while (entry != NULL) { 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; } @@ -434,7 +440,7 @@ HashEntry* hashmap_get_entry(const HashMap* hm, const char* key) { while (entry != NULL) { 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; } @@ -452,7 +458,7 @@ HashEntry* hashmap_get_entry(const HashMap* hm, const char* key, uint64 hash) { while (entry != NULL) { 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; } @@ -664,7 +670,7 @@ HashEntryKeyInt32* hashmap_get_entry(const HashMap* hm, int32 key) { while (entry != NULL) { if (entry->key == key) { - DEBUG_MEMORY_READ((uint64) entry, sizeof(HashEntryKeyInt32)); + DEBUG_MEMORY_READ((uintptr_t) entry, sizeof(HashEntryKeyInt32)); return entry; } @@ -682,7 +688,7 @@ HashEntryKeyInt32* hashmap_get_entry(const HashMap* hm, int32 key, uint64 hash) while (entry != NULL) { if (entry->key == key) { - DEBUG_MEMORY_READ((uint64) entry, sizeof(HashEntryKeyInt32)); + DEBUG_MEMORY_READ((uintptr_t) entry, sizeof(HashEntryKeyInt32)); return entry; } @@ -851,6 +857,8 @@ int64 hashmap_load(HashMap* hm, const byte* data) } chunk_iterate_end; + LOG_LEVEL_2("Loaded HashMap: %n B", {{LOG_DATA_UINT64, &hm->buf.size}}); + // How many bytes was read from data return sizeof(hm->buf.count) // hash map count = buffer count + hm->buf.count * sizeof(uint64) // table content diff --git a/stdlib/Types.h b/stdlib/Types.h index ae27c29..48ce68b 100644 --- a/stdlib/Types.h +++ b/stdlib/Types.h @@ -54,6 +54,42 @@ typedef char sbyte; typedef uintptr_t umm; 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 MEGABYTE 1048576 #define GIGABYTE 1073741824 @@ -203,6 +239,10 @@ struct v2_f32 { f32 x, y; }; + struct { + f32 width, height; + }; + f32 v[2]; }; }; diff --git a/thread/Thread.h b/thread/Thread.h index 672ba9a..372ff8d 100644 --- a/thread/Thread.h +++ b/thread/Thread.h @@ -26,6 +26,7 @@ void thread_create(Worker* worker, ThreadJobFunc routine, void* arg) { + LOG_LEVEL_2("Thread started", {}); pthread_create(&worker->thread, NULL, routine, arg); } @@ -33,6 +34,7 @@ void thread_stop(Worker* worker) { atomic_set_acquire(&worker->state, 0); pthread_join(worker->thread, NULL); + LOG_LEVEL_2("Thread ended", {}); } #endif \ No newline at end of file diff --git a/thread/ThreadPool.h b/thread/ThreadPool.h index 5933644..6026034 100644 --- a/thread/ThreadPool.h +++ b/thread/ThreadPool.h @@ -63,9 +63,12 @@ static THREAD_RETURN thread_pool_worker(void* arg) atomic_increment_relaxed(&pool->working_cnt); atomic_set_release(&work->state, 2); + LOG_LEVEL_2("ThreadPool worker started", {}); work->func(work); + LOG_LEVEL_2("ThreadPool worker ended", {}); // 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); // Job gets marked after completion -> can be overwritten now diff --git a/utils/MathUtils.h b/utils/MathUtils.h deleted file mode 100644 index c4838a5..0000000 --- a/utils/MathUtils.h +++ /dev/null @@ -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 - -#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 diff --git a/utils/StringUtils.h b/utils/StringUtils.h index 06ff849..e3f30b7 100644 --- a/utils/StringUtils.h +++ b/utils/StringUtils.h @@ -15,7 +15,6 @@ #include #include "../stdlib/Types.h" -#include "MathUtils.h" inline int32 utf8_encode(uint32 codepoint, char* out) @@ -80,6 +79,39 @@ int32 utf8_decode(const char* __restrict in, uint32* __restrict codepoint) { 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 int32 utf8_strlen(const char* in) { int32 length = 0; @@ -400,6 +432,17 @@ int32 str_copy_until(char* __restrict dest, const char* __restrict src, char del 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 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_start(args, format); - const char* ptr = format; - char *buf_ptr = buffer; - - while (*ptr) { - if (*ptr != '%') { - *buf_ptr++ = *ptr; - } else if (*ptr == '\\' && *(ptr + 1) == '%') { - ++ptr; - *buf_ptr++ = *ptr; + while (*format) { + if (*format != '%') { + *buffer++ = *format; + } else if (*format == '\\' && *(format + 1) == '%') { + ++format; + *buffer++ = *format; } else { - ++ptr; + ++format; - switch (*ptr) { + switch (*format) { case 's': { const char* str = va_arg(args, const char*); while (*str) { - *buf_ptr++ = *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); - if (val < 0) { - *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]; - } + buffer += int_to_str(val, buffer); } break; case 'l': { int64 val = va_arg(args, int64); - if (val < 0) { - *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]; - } + buffer += int_to_str(val, buffer); } break; case 'f': { f64 val = va_arg(args, f64); @@ -1049,7 +1066,7 @@ void sprintf_fast(char *buffer, const char* format, ...) { int32 precision = 5; // Check for optional precision specifier - const char* prec_ptr = ptr + 1; + const char* prec_ptr = format + 1; if (*prec_ptr >= '0' && *prec_ptr <= '9') { precision = 0; while (*prec_ptr >= '0' && *prec_ptr <= '9') { @@ -1057,11 +1074,11 @@ void sprintf_fast(char *buffer, const char* format, ...) { prec_ptr++; } - ptr = prec_ptr - 1; + format = prec_ptr - 1; } if (val < 0) { - *buf_ptr++ = '-'; + *buffer++ = '-'; val = -val; } @@ -1087,31 +1104,143 @@ void sprintf_fast(char *buffer, const char* format, ...) { } while (int_part > 0); while (index > 0) { - *buf_ptr++ = temp[--index]; + *buffer++ = temp[--index]; } // Handle fractional part if (precision > 0) { - *buf_ptr++ = '.'; + *buffer++ = '.'; while (precision--) { frac_part *= 10; int32 digit = (int32) frac_part; - *buf_ptr++ = (char) (digit + '0'); + *buffer++ = (char) (digit + '0'); frac_part -= digit; } } } break; default: { // Handle unknown format specifiers - *buf_ptr++ = '%'; + *buffer++ = '%'; } 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); }