mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-10 19:08:39 +00:00
bug fixes, improved input handling and started testing with typing mode
This commit is contained in:
parent
2ecb47117b
commit
a02963607d
|
|
@ -10,8 +10,8 @@
|
|||
#ifndef TOS_ANIMATION_H
|
||||
#define TOS_ANIMATION_H
|
||||
|
||||
#include <math.h>
|
||||
#include "../stdlib/Types.h"
|
||||
#include "../utils/MathUtils.h"
|
||||
|
||||
#include "AnimationEaseType.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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "../../EngineDependencies/curl/include/curl/curl.h"
|
||||
#include "../utils/MathUtils.h"
|
||||
|
||||
#define MAX_AUTH_POST_LENGTH 1024
|
||||
#define MAX_AUTH_RESPONSE_LENGTH 1024
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "../stdlib/Types.h"
|
||||
#include "../utils/BitUtils.h"
|
||||
#include "../utils/MathUtils.h"
|
||||
#include "../utils/EndianUtils.h"
|
||||
|
||||
struct HuffmanNode {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#define TOS_ENVIRONMENT_GLOBE_H
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
#include "../utils/MathUtils.h"
|
||||
#include <math.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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
653
input/Input.h
653
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 <windows.h>
|
||||
#include <dinput.h>
|
||||
#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
|
||||
192
log/Debug.cpp
192
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
|
||||
49
log/Debug.h
49
log/Debug.h
|
|
@ -18,15 +18,56 @@
|
|||
#include <windows.h>
|
||||
#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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
56
log/Log.h
56
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
|
||||
|
|
@ -12,7 +12,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -12,7 +12,6 @@
|
|||
#include <immintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include "../../utils/MathUtils.h"
|
||||
#include "../../stdlib/Simd.h"
|
||||
|
||||
struct v3_int32_4 {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include <immintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include "../../utils/MathUtils.h"
|
||||
#include "../../stdlib/Simd.h"
|
||||
|
||||
struct v3_int64_2 {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <string.h>
|
||||
#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;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include <immintrin.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#ifndef TOS_MODELS_MOB_C
|
||||
#define TOS_MODELS_MOB_C
|
||||
|
||||
#include "../../utils/MathUtils.h"
|
||||
#include "Mob.h"
|
||||
#include "MobState.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?
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
#include "../utils/MathUtils.h"
|
||||
|
||||
struct JPSNode {
|
||||
int32 x, y;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#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);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
#include "../utils/MathUtils.h"
|
||||
|
||||
struct Path {
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../../utils/MathUtils.h"
|
||||
|
||||
#include "JpsGrid.h"
|
||||
#include "../Path.h"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../../utils/MathUtils.h"
|
||||
|
||||
#include "JpsNode.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../../utils/MathUtils.h"
|
||||
|
||||
struct JpsNode {
|
||||
bool is_walkable;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -9,10 +9,27 @@
|
|||
#ifndef TOS_PLATFORM_WIN32_UTILS_H
|
||||
#define TOS_PLATFORM_WIN32_UTILS_H
|
||||
|
||||
#include "../../stdlib/Types.h"
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @package Utils
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_UTILS_MATH_UTILS_H
|
||||
#define TOS_UTILS_MATH_UTILS_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define OMS_PI 3.14159265358979323846f
|
||||
#define OMS_PI_OVER_TWO (OMS_PI / 2.0f)
|
||||
#define OMS_PI_OVER_FOUR (OMS_PI / 4.0f)
|
||||
#define OMS_TWO_PI (2.0f * OMS_PI)
|
||||
|
||||
#define OMS_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define OMS_MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
#define OMS_CLAMP(val, high, low) (OMS_MAX(OMS_MIN((val), (high)), (low)))
|
||||
#define OMS_ABS(a) ((a) > 0 ? (a) : -(a))
|
||||
#define OMS_DEG2RAD(angle) ((angle) * OMS_PI / 180.0f)
|
||||
#define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI)
|
||||
#define ROUND_TO_NEAREST(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
|
||||
#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
|
||||
#define OMS_CEIL(x) ((x) == (int)(x) ? (int)(x) : ((x) > 0 ? (int)(x) + 1 : (int)(x)))
|
||||
#define OMS_ROUND(x) (((x) >= 0) ? ((int)((x) + 0.5f)) : ((int)((x) - 0.5f)))
|
||||
#define OMS_ROUND_POSITIVE(x) ((int)((x) + 0.5f))
|
||||
#define FLOAT_CAST_EPS 0.001953125
|
||||
|
||||
// Modulo function when b is a power of 2
|
||||
#define MODULO_2(a, b) ((a) & (b - 1))
|
||||
|
||||
#define SQRT_2 1.4142135623730950488016887242097f
|
||||
|
||||
#endif
|
||||
|
|
@ -15,7 +15,6 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user