Initial commit
This is working repository now. I had to clean this up due to my f_ups, that made this simple repo around 200MB large. Signed-off-by: Piotr Krygier <piotrkrygier@everyonecancode@xyz>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file commons.h
|
||||
* @author Piotr Krygier (everyonecancode@gmail.com)
|
||||
* @brief Common functionality for all modules
|
||||
* @version 0.1
|
||||
* @date 2023-10-05
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMMONS_H
|
||||
#define COMMONS_H
|
||||
|
||||
#include <SDL3/SDL_log.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Macro for allocating memory and checking it on the same line
|
||||
*
|
||||
*/
|
||||
#ifndef RSE_TEST
|
||||
#define rse_malloc(ptr, size) \
|
||||
ptr = malloc(size); \
|
||||
if (ptr == NULL) { \
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Memory allocation failure"); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define rse_free(ptr) free(ptr);
|
||||
|
||||
#define rse_memcpy(dst, src, size) memcpy(dst, src, size);
|
||||
#define rse_memset(ptr, value, size) memset(ptr, value, size);
|
||||
#else
|
||||
#define rse_malloc(ptr, size) ptr = NULL;
|
||||
#define rse_free(ptr)
|
||||
#define rse_memcpy(dst, src, size)
|
||||
#define rse_memset
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Error type for RSE
|
||||
*
|
||||
*/
|
||||
typedef uint32_t rse_err_t;
|
||||
|
||||
#endif /* COMMONS_H */
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @file entity.h
|
||||
* @author Piotr Krygier (piotrkrygier@everyonencancode.xyz)
|
||||
* @brief Entity from ECS
|
||||
* @version 0.1
|
||||
* @date 2025-09-25
|
||||
*
|
||||
* @copyright Copyright (c) 2025
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ENTITY_H
|
||||
#define ENTITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ENTITY_MAX_COUNT 65535
|
||||
#define COMPONENT_MAX_COUNT 65535
|
||||
|
||||
typedef uint32_t entity_t;
|
||||
|
||||
entity_t entity_create(void);
|
||||
void entity_free(entity_t entity);
|
||||
|
||||
#endif // !ENTITY_H
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @file errors_common.h
|
||||
* @author Piotr Krygier (everyonecancode@gmail.com)
|
||||
* @brief Common error messages, that can appear in any module
|
||||
* @version 0.1
|
||||
* @date 2023-10-05
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ERRORS_COMMON_H
|
||||
|
||||
/* Macro for checking status of function execution in initVulkan. Created to avoid writing boilerplate code */
|
||||
#define STATUS_CHECK(FUNC) \
|
||||
status = FUNC; \
|
||||
if (RSE_ERROR_NO_ERROR != status) { \
|
||||
return status; \
|
||||
}
|
||||
|
||||
#define RSE_COMMON_MODULE_ID 0x0100U
|
||||
|
||||
enum common_error_t
|
||||
{
|
||||
RSE_ERROR_NO_ERROR = RSE_COMMON_MODULE_ID,
|
||||
RSE_ERROR_NULL_POINTER,
|
||||
RSE_ERROR_ALREADY_INITIALIZED,
|
||||
RSE_COMMON_ERROR_MALLLOC_FAILED,
|
||||
RSE_ERROR_INVALID_PARAM,
|
||||
RSE_ERROR_INTERNAL_ERROR,
|
||||
};
|
||||
|
||||
#define ERRORS_COMMON_H
|
||||
#endif /* ERRORS_COMMON_H */
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef FILE_UTILS_H
|
||||
#define FILE_UTILS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "commons.h"
|
||||
|
||||
#define MAX_PATH_LENGTH (4096U)
|
||||
|
||||
/**
|
||||
* @brief Reads file and puts its content into char buffer. If NULL is provided as buffer, than just bytes_count
|
||||
* is set
|
||||
*
|
||||
* @param file_path Path to file
|
||||
* @param bytes_count Returned bytes count
|
||||
* @param buffer Returned filled buffer
|
||||
*/
|
||||
rse_err_t file_read(const char* file_path, size_t* bytes_count, char* buffer);
|
||||
|
||||
rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer);
|
||||
|
||||
rse_err_t file_load_pixels(const char* file_name, unsigned char* buffer, size_t* buffer_size, int* width, int* height);
|
||||
|
||||
rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size);
|
||||
|
||||
#endif /* FILE_UTILS_H */
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
rse_utilities_srcs = [
|
||||
'src/file_utils.c'
|
||||
]
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
sdl3_dep = dependency('sdl3',
|
||||
version : '>=3.4.0')
|
||||
stb_dep = dependency('stb',
|
||||
version : '>=2.30.0')
|
||||
m_dep = cc.find_library('m')
|
||||
|
||||
rse_utilities_lib = shared_library(
|
||||
'rse_utilities',
|
||||
rse_utilities_srcs,
|
||||
include_directories : ['.'],
|
||||
dependencies : [
|
||||
sdl3_dep,
|
||||
stb_dep,
|
||||
m_dep,
|
||||
],
|
||||
install : true
|
||||
)
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @file entity.c
|
||||
* @author Piotr Krygier (piotrkrygier@everyonencancode.xyz)
|
||||
* @brief Entity from ECS
|
||||
* @version 0.1
|
||||
* @date 2025-09-25
|
||||
*
|
||||
* @copyright Copyright (c) 2025
|
||||
*
|
||||
*/
|
||||
|
||||
#include "utilities/entity.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static entity_t g_free_list[ENTITY_MAX_COUNT];
|
||||
static uint32_t g_free_count = 0U;
|
||||
static uint32_t g_living_count = 0U;
|
||||
|
||||
entity_t entity_create(void)
|
||||
{
|
||||
entity_t e = 0U;
|
||||
if (g_free_count > 0) {
|
||||
e = g_free_list[g_free_count--];
|
||||
} else {
|
||||
e = g_living_count++;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void entity_free(entity_t entity)
|
||||
{
|
||||
g_free_list[g_free_count++] = entity;
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
#include "file_utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL3/SDL_log.h"
|
||||
#include "commons.h"
|
||||
#include "errors_common.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb/stb_image.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#endif /* ifndef __linux */
|
||||
|
||||
static rse_err_t get_curr_path(char* path)
|
||||
{
|
||||
char* last_sep = NULL;
|
||||
char* tmp_path = NULL;
|
||||
size_t path_length = 0U;
|
||||
ssize_t binary_path_length = 0U;
|
||||
size_t directory_path_length = 0U;
|
||||
|
||||
if (NULL == path) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to get path. Provided pointer is NULL");
|
||||
|
||||
return RSE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
path_length = strlen(path);
|
||||
if (path_length > MAX_PATH_LENGTH) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Max path length cannot be 0");
|
||||
|
||||
return RSE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
rse_memset(path, '\0', path_length);
|
||||
rse_malloc(tmp_path, MAX_PATH_LENGTH);
|
||||
|
||||
#ifdef __linux__
|
||||
binary_path_length = readlink("/proc/self/exe", tmp_path, MAX_PATH_LENGTH - 1);
|
||||
if (binary_path_length == -1) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to read current binary path");
|
||||
|
||||
return RSE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
tmp_path[binary_path_length] = '\0';
|
||||
#endif /* ifdef __linux__ */
|
||||
|
||||
last_sep = strrchr(tmp_path, '/') + 1;
|
||||
|
||||
if (NULL == last_sep) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to get last separator in path");
|
||||
|
||||
return RSE_ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
directory_path_length = last_sep - tmp_path;
|
||||
|
||||
if (directory_path_length > MAX_PATH_LENGTH) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Provided path buffer is too small");
|
||||
|
||||
return RSE_ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
strncpy(path, tmp_path, directory_path_length);
|
||||
|
||||
free(tmp_path);
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size)
|
||||
{
|
||||
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
||||
size_t curr_path_length = 0U;
|
||||
size_t file_path_length = 0U;
|
||||
char curr_path[MAX_PATH_LENGTH] = {0};
|
||||
char temp_path[MAX_PATH_LENGTH] = {0};
|
||||
|
||||
file_path_length = strlen(file_path);
|
||||
|
||||
if (file_path_length > max_buffer_size) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided max_buffer_size is smaller than the file path itself");
|
||||
|
||||
return RSE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if ((ret = get_curr_path(curr_path)) != RSE_ERROR_NO_ERROR) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
curr_path_length = strlen(curr_path);
|
||||
|
||||
if ((curr_path_length + file_path_length) > max_buffer_size) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Provided max_buffer_size is to small to hold concatenated file path. %ld vs %ld",
|
||||
(curr_path_length + file_path_length),
|
||||
max_buffer_size);
|
||||
}
|
||||
|
||||
strncpy(temp_path, file_path, MAX_PATH_LENGTH);
|
||||
|
||||
memset(file_path, 0, max_buffer_size);
|
||||
|
||||
strncat(file_path, curr_path, max_buffer_size);
|
||||
strncat(file_path, temp_path, max_buffer_size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rse_err_t file_load_pixels(const char* file_name, unsigned char* buffer, size_t* buffer_size, int* width, int* height)
|
||||
{
|
||||
int channels = 0;
|
||||
stbi_uc* pixel_buffer = NULL;
|
||||
size_t image_buffer_size = 0U;
|
||||
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
||||
char real_path[MAX_PATH_LENGTH] = {0};
|
||||
|
||||
if (buffer_size == NULL) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL buffer_size");
|
||||
|
||||
return RSE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (width == NULL) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL width");
|
||||
|
||||
return RSE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (height == NULL) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL height");
|
||||
|
||||
return RSE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
||||
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pixel_buffer = stbi_load(real_path, width, height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (pixel_buffer == NULL) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to load texture from file: %s", file_name);
|
||||
return RSE_ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
image_buffer_size = *width * *height * 4; // TODO: "4" is very hardcoded value. Change this
|
||||
|
||||
if ((buffer != NULL) && (image_buffer_size > *buffer_size)) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Provided buffer is to small to hold pixel data. %ld vs %ld",
|
||||
*buffer_size,
|
||||
image_buffer_size);
|
||||
ret = RSE_ERROR_INTERNAL_ERROR;
|
||||
|
||||
goto image_free;
|
||||
}
|
||||
|
||||
*buffer_size = image_buffer_size;
|
||||
|
||||
if (buffer != NULL) {
|
||||
memset(buffer, 0, *buffer_size);
|
||||
memcpy(buffer, pixel_buffer, *buffer_size);
|
||||
}
|
||||
|
||||
image_free:
|
||||
stbi_image_free(pixel_buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rse_err_t file_read(const char* file_name, size_t* bytes_count, char* buffer)
|
||||
{
|
||||
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
||||
FILE* file = NULL;
|
||||
char real_path[MAX_PATH_LENGTH] = {0};
|
||||
|
||||
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
||||
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
file = fopen(real_path, "rb");
|
||||
|
||||
if (file == NULL) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to open file for read: %s", real_path);
|
||||
ret = RSE_ERROR_INTERNAL_ERROR;
|
||||
|
||||
goto file_close;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
*bytes_count = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
if (buffer == NULL) {
|
||||
goto file_close;
|
||||
}
|
||||
|
||||
fread(buffer, *bytes_count, 1, file);
|
||||
if (ferror(file) != 0) {
|
||||
perror("Error reading file");
|
||||
|
||||
ret = RSE_ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
file_close:
|
||||
fclose(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer)
|
||||
{
|
||||
FILE* file = NULL;
|
||||
char real_path[MAX_PATH_LENGTH] = {0};
|
||||
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
||||
|
||||
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
||||
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
file = fopen(real_path, "wb");
|
||||
|
||||
if (file == NULL) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to open file for write: %s", file_name);
|
||||
return RSE_ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
fwrite(buffer, bytes_count, 1, file);
|
||||
fclose(file);
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file stack.h
|
||||
* @author Piotr Krygier (everyonecancode@gmail.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-05-01
|
||||
*
|
||||
* @copyright Copyright (c) 2024
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
#define RSE_STACK_DEFINE(name, type, size) \
|
||||
struct name { \
|
||||
type data[size]; \
|
||||
int top; \
|
||||
}
|
||||
|
||||
#define RSE_STACK_PUSH(stack, value) \
|
||||
stack.data[++stack.top] = value
|
||||
|
||||
#define RSE_STACK_POP(stack) \
|
||||
stack.data[stack.top--]
|
||||
|
||||
#define RSE_STACK_TOP(stack) \
|
||||
stack.data[stack.top]
|
||||
|
||||
#define RSE_STACK_IS_EMPTY(stack) \
|
||||
(stack.top == -1)
|
||||
|
||||
#define RSE_STACK_IS_FULL(stack, size) \
|
||||
(stack.top == size - 1)
|
||||
|
||||
#define RSE_STACK_INIT(stack) \
|
||||
(stack.top = -1)
|
||||
|
||||
#define RSE_STACK_SIZE(stack) \
|
||||
(stack.top + 1)
|
||||
|
||||
#define RSE_STACK_CLEAR(stack) \
|
||||
(stack.top = -1)
|
||||
|
||||
#endif // STACK_H
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @file vector.h
|
||||
* @author Piotr Krygier (piotrkrygier@everyonecancode.xyz)
|
||||
* @brief C implementation of a vector, dynamic array
|
||||
* @version 0.1
|
||||
* @date 2024-09-18
|
||||
*
|
||||
* @copyright Copyright (c) 2025
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VECTOR_H
|
||||
#define VECTOR_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL3/SDL_log.h"
|
||||
#include "utilities/commons.h"
|
||||
#include "utilities/errors_common.h"
|
||||
|
||||
#define VECTOR_CHUNK_SIZE (64U)
|
||||
#define RSE_VECTOR_DEFINE(name, type) \
|
||||
struct name \
|
||||
{ \
|
||||
type* data; \
|
||||
size_t size; \
|
||||
size_t _allocated_size; \
|
||||
}
|
||||
|
||||
#define RSE_VECTOR_PUSH_BACK(vector, value) \
|
||||
{ \
|
||||
if (vector.data == NULL) { \
|
||||
vector.size = 0; \
|
||||
vector._allocated_size = VECTOR_CHUNK_SIZE; \
|
||||
rse_malloc(vector.data, sizeof(*vector.data) * VECTOR_CHUNK_SIZE); \
|
||||
} \
|
||||
if (vector._allocated_size == vector.size) { \
|
||||
__typeof__((vector.data)) tmp_buffer = NULL; \
|
||||
rse_malloc(tmp_buffer, sizeof(*vector.data) * vector.size); \
|
||||
rse_memcpy(tmp_buffer, vector.data, sizeof(*vector.data) * vector.size); \
|
||||
rse_free(vector.data); \
|
||||
vector._allocated_size += VECTOR_CHUNK_SIZE; \
|
||||
rse_malloc(vector.data, vector._allocated_size * vector.size); \
|
||||
rse_memcpy(vector.data, tmp_buffer, sizeof(*vector.data) * vector.size); \
|
||||
rse_free(tmp_buffer); \
|
||||
} \
|
||||
vector.data[vector.size] = value; \
|
||||
vector.size++; \
|
||||
}
|
||||
|
||||
#define RSE_VECTOR_INSERT_INTO(vector, idx, data) \
|
||||
{ \
|
||||
if (vector._allocated_size == vector.size) { \
|
||||
__typeof__((vector.data)) tmp_buffer = NULL; \
|
||||
rse_malloc(tmp_buffer, sizeof(*vector.data) * vector.size); \
|
||||
rse_memcpy(tmp_buffer, vector.data, sizeof(*vector.data) * vector.size); \
|
||||
if (vector.data != NULL) { \
|
||||
rse_free(vector.data); \
|
||||
} \
|
||||
vector._allocated_size += VECTOR_CHUNK_SIZE; \
|
||||
rse_malloc(vector.data, vector._allocated_size * vector.size); \
|
||||
rse_memcpy(vector.data, tmp_buffer, sizeof(*vector.data) * vector.size); \
|
||||
rse_free(tmp_buffer); \
|
||||
} \
|
||||
vector->size++; \
|
||||
rse_memcpy(&vector->data[idx + 1], &vector->data[idx], sizeof(*vector->data) * (vector->size - idx)); \
|
||||
vector->data[idx] = data; \
|
||||
}
|
||||
|
||||
#define RSE_VECTOR_REMOVE_ELEMENT(vector, idx) \
|
||||
{ \
|
||||
if (vector->size <= idx) { \
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Vector index out of bounds"); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
if (vector->size == 1) { \
|
||||
rse_free(vector->data); \
|
||||
vector->_allocated_size = 0; \
|
||||
} else { \
|
||||
rse_memcpy(&vector->data[idx], &vector->data[idx + 1], sizeof(vector->data) * (vector->size - idx - 1)); \
|
||||
} \
|
||||
vector->size--; \
|
||||
}
|
||||
|
||||
struct vector_t
|
||||
{
|
||||
void* data;
|
||||
size_t size;
|
||||
size_t _data_size;
|
||||
size_t _allocated_size;
|
||||
};
|
||||
|
||||
#endif // !VECTOR_H
|
||||
Reference in New Issue
Block a user