#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