diff --git a/Makefile b/Makefile index f7c0c5f..86a9067 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ else debug_flags := $(debug_flags) -Og -feliminate-unused-debug-symbols tui_library_flags := -lncursesw endif -common_source_files := field.c sim.c +common_source_files := field.c mark.c sim.c tui_source_files := $(common_source_files) tui_main.c cli_source_files := $(common_source_files) cli_main.c diff --git a/base.h b/base.h index 903de39..777813f 100644 --- a/base.h +++ b/base.h @@ -8,10 +8,19 @@ #include #include +#if defined(__GNUC__) || defined(__clang__) +#define ORCA_FORCE_INLINE __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +#define ORCA_FORCE_INLINE __forceinline +#else +#define ORCA_FORCE_INLINE inline +#endif + #define ORCA_Y_MAX UINT16_MAX #define ORCA_X_MAX UINT16_MAX -typedef char Glyph; +typedef uint8_t U8; +typedef int8_t I8; typedef uint16_t U16; typedef int16_t I16; typedef uint32_t U32; @@ -21,6 +30,8 @@ typedef int64_t I64; typedef size_t Usz; typedef ssize_t Isz; +typedef char Glyph; + typedef struct { Glyph* buffer; U16 height; diff --git a/mark.c b/mark.c new file mode 100644 index 0000000..57f6806 --- /dev/null +++ b/mark.c @@ -0,0 +1,21 @@ +#include "mark.h" + +void markmap_init(Markmap* map) { + map->buffer = NULL; + map->capacity = 0; +} + +void markmap_ensure_capacity(Markmap* map, Usz capacity) { + if (map->capacity < capacity) { + map->buffer = realloc(map->buffer, capacity); + map->capacity = capacity; + } +} + +void markmap_clear(Markmap* map) { + memset(map->buffer, 0, map->capacity); +} + +void markmap_deinit(Markmap* map) { + free(map->buffer); +} diff --git a/mark.h b/mark.h new file mode 100644 index 0000000..b64da47 --- /dev/null +++ b/mark.h @@ -0,0 +1,49 @@ +#pragma once +#include "base.h" + +typedef enum { + Mark_flag_none = 0, + Mark_flag_haste_input = 1 << 0, + Mark_flag_input = 1 << 1, + Mark_flag_lock = 1 << 2, + Mark_flag_output = 1 << 3, +} Mark_flags; + +typedef struct { + U8* buffer; + Usz capacity; +} Markmap; + +void markmap_init(Markmap* map); +void markmap_ensure_capacity(Markmap* map, Usz capacity); +void markmap_clear(Markmap* map); +void markmap_deinit(Markmap* map); + +ORCA_FORCE_INLINE +Mark_flags markmap_peek_relative(Markmap* map, Usz map_height, Usz map_width, + Usz y, Usz x, Isz offs_y, Isz offs_x); +ORCA_FORCE_INLINE +void markmap_poke_relative(Markmap* map, Usz map_height, Usz map_width, Usz y, + Usz x, Isz offs_y, Isz offs_x, Mark_flags flags); + +// Inline implementation + +ORCA_FORCE_INLINE +Mark_flags markmap_peek_relative(Markmap* map, Usz map_height, Usz map_width, + Usz y, Usz x, Isz offs_y, Isz offs_x) { + Isz y0 = (Isz)y + offs_y; + Isz x0 = (Isz)x + offs_x; + if (y0 >= (Isz)map_height || x0 >= (Isz)map_width || y0 < 0 || x0 < 0) + return Mark_flag_none; + return map->buffer[(Usz)y0 * map_width + (Usz)x0]; +} + +ORCA_FORCE_INLINE +void markmap_poke_relative(Markmap* map, Usz map_height, Usz map_width, Usz y, + Usz x, Isz offs_y, Isz offs_x, Mark_flags flags) { + Isz y0 = (Isz)y + offs_y; + Isz x0 = (Isz)x + offs_x; + if (y0 >= (Isz)map_height || x0 >= (Isz)map_width || y0 < 0 || x0 < 0) + return; + map->buffer[(Usz)y0 * map_width + (Usz)x0] = flags; +}