diff options
| author | Peter Fors <peter.fors@mindkiller.com> | 2025-03-29 20:11:56 +0100 |
|---|---|---|
| committer | Peter Fors <peter.fors@mindkiller.com> | 2025-03-29 20:11:56 +0100 |
| commit | d5486a5af100fb37fac08b60d862ac14943853ce (patch) | |
| tree | e2206f620745ba49c94f0f29d180587e03bc9fda /base/state.c | |
| parent | ee4f15400998ca704c6ad8fc537f0d924930fabd (diff) | |
add base code for windowing and opengl crt-shader.
Diffstat (limited to 'base/state.c')
| -rw-r--r-- | base/state.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/base/state.c b/base/state.c new file mode 100644 index 0000000..f883d64 --- /dev/null +++ b/base/state.c @@ -0,0 +1,134 @@ + +#define BUFFER_WIDTH 2048 +#define BUFFER_HEIGHT 1024 +#define FPS 50 +#ifdef _WIN32 + #define SLEEP_MARGIN_NS 330000 // 0.33ms (Windows timing functionality is utter garbage) +#else + #define SLEEP_MARGIN_NS 100000 // 0.1ms +#endif + +#define ONE_SECOND_NS 1000000000 +#define FRAMETIME (ONE_SECOND_NS / FPS) + +#define SCREEN_WIDTH 360 +#define SCREEN_HEIGHT 270 + +uint32_t buffer[BUFFER_WIDTH * BUFFER_HEIGHT] __attribute__((section(".bss"), aligned(4096))); +uint32_t display_buffer[SCREEN_WIDTH * SCREEN_HEIGHT] __attribute__((section(".bss"), aligned(4096))); + +#ifdef PROFILER +#define MAX_PROFILING_ENTRIES (64) + +struct function_cycles { + const char *name; + uint64_t cycles; + uint32_t count; +}; + +struct debug_state { + struct function_cycles timings[MAX_PROFILING_ENTRIES]; +}; +#endif + +struct state { + // Pointers (8-byte aligned) + uint32_t *display_buffer; + struct { int32_t x, y, w, h; } viewport; + int32_t mouse_dx; + int32_t mouse_dy; + int32_t filter_override; // Manual override: -1 = automatic, 0 = off, 1 = on + float filter_frequency; // Frequency in Hz for squarewave toggle + + float contrast; + float saturation; + float brightness; + float tone_data[4]; + + // OpenGL Objects + GLuint shader_program; + GLuint texture; + GLuint vao; + GLuint vbo; + GLuint ebo; + + // Shader Uniforms + GLuint uniform_resolution; + GLuint uniform_src_image_size; + GLuint uniform_brightness; + GLuint uniform_tone; + GLuint uniform_crt_emulation; + GLuint uniform_sampler_location; + GLuint uniform_tex_bounds; + + // Rendering & Dynamic Resolution + uint32_t screen_width; // for the debugger + uint32_t screen_height; // for the debugger + uint32_t render_width; // The actual remake resolution (e.g., 360) + uint32_t render_height; // The actual remake resolution (e.g., 270) + uint32_t render_x; // X position inside BUFFER_WIDTH (to track centering) + uint32_t render_y; // Y position inside BUFFER_HEIGHT (to track centering) + uint32_t frame_number; + size_t total_allocated; + bool freewheeling; + bool toggle_crt_emulation; + bool fullscreen; +#ifdef PROFILER + bool overlay; + struct debug_state debug; +#endif +}; + +struct state state; + +static struct remake_callbacks *current_part = 0; +static void render_callback(); +static void audio_callback(int16_t *audio_buffer, size_t frames); +static void init_callback(); + +#ifndef PROFILER +#define PROFILE_NAMED(name) +#define PROFILE_FUNCTION() + +#else + +struct profiling_context { + uint32_t func_id; +}; + +__attribute__((section(".bss"))) +uint8_t debug_line_buffer[MAX_PROFILING_ENTRIES * 256]; // NOTE(peter): for storing all performance strings in an array to print to the debug-output + +__attribute__((always_inline, hot)) +static inline uint64_t read_tsc() { + unsigned int aux; + uint64_t result = __rdtscp(&aux); + return result; +} + +__attribute__((always_inline, hot)) +static inline void end_profiling(struct profiling_context *ctx) __attribute__((unused)); +__attribute__((always_inline, hot)) +static inline void end_profiling(struct profiling_context *ctx) { + state.debug.timings[ctx->func_id].cycles += read_tsc(); + state.debug.timings[ctx->func_id].count++; +} + +#define PROFILE_NAMED(name) \ + uint32_t func_id = __COUNTER__; \ + if((state).debug.timings[func_id].count == 0) \ + (state).debug.timings[func_id] = (struct function_cycles){(name), 0, 0}; \ + (state).debug.timings[func_id].cycles -= read_tsc(); \ + struct profiling_context ctx __attribute__((cleanup(end_profiling))) = { func_id }; + +#define PROFILE_FUNCTION() \ + uint32_t func_id = __COUNTER__; \ + if((state).debug.timings[func_id].count == 0) \ + (state).debug.timings[func_id] = (struct function_cycles){__func__, 0, 0}; \ + (state).debug.timings[func_id].cycles -= read_tsc(); \ + struct profiling_context ctx __attribute__((cleanup(end_profiling))) = { func_id }; +#endif + + + + |
