Skip to content

Instantly share code, notes, and snippets.

@JettMonstersGoBoom
Created June 25, 2024 16:29
Show Gist options
  • Save JettMonstersGoBoom/2231c2852d1ebe46bdf9b98b8d525c3f to your computer and use it in GitHub Desktop.
Save JettMonstersGoBoom/2231c2852d1ebe46bdf9b98b8d525c3f to your computer and use it in GitHub Desktop.
//
// drop in to sdl3_template for a fixed framebuffer experience
//
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_stdinc.h>
#include <math.h>
// "game" size
#define APP_WIDTH 384
#define APP_HEIGHT 216
// see SDL_pixels.h for options
#define APP_PIXEL_FORMAT SDL_PIXELFORMAT_XRGB4444
// bytes per pixel
#define APP_PIXEL_SIZE 2
// test function to draw a pixel
void plot(Sint16 x, Sint16 y, Uint32 c);
struct {
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Texture* fb_texture;
SDL_bool app_quit;
void *buffer;
}AppContext;
int SDL_Fail(){
SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError());
return -1;
}
int SDL_AppInit(void** appstate, int argc, char* argv[])
{
memset(&AppContext, 0, sizeof(AppContext));
AppContext.app_quit = SDL_FALSE;
// init the library, here we make a window so we only need the Video capabilities.
if (SDL_Init(SDL_INIT_VIDEO)){
return SDL_Fail();
}
// create a window
AppContext.window = SDL_CreateWindow("Window", APP_WIDTH, APP_HEIGHT, SDL_WINDOW_RESIZABLE);
if (!AppContext.window){
return SDL_Fail();
}
AppContext.renderer = SDL_CreateRenderer(AppContext.window, NULL);
if (!AppContext.renderer){
return SDL_Fail();
}
// create texture the same format and size as the "game"
AppContext.fb_texture = SDL_CreateTexture(AppContext.renderer, APP_PIXEL_FORMAT, SDL_TEXTUREACCESS_STREAMING, APP_WIDTH, APP_HEIGHT);
// create a raw pixel buffer the same
AppContext.buffer = (void*)SDL_calloc(APP_PIXEL_SIZE,APP_WIDTH * APP_HEIGHT );
if (!AppContext.buffer) {
return SDL_Fail();
}
// print some information about the window
SDL_ShowWindow(AppContext.window);
{
int width, height, bbwidth, bbheight;
SDL_GetWindowSize(AppContext.window, &width, &height);
SDL_GetWindowSizeInPixels(AppContext.window, &bbwidth, &bbheight);
SDL_Log("Window size: %ix%i", width, height);
SDL_Log("Backbuffer size: %ix%i", bbwidth, bbheight);
if (width != bbwidth){
SDL_Log("This is a highdpi environment.");
}
}
SDL_Log("Application started successfully!");
// handles resize of window, includes black borders
// currently uses NEAREST filter
SDL_SetRenderLogicalPresentation(AppContext.renderer, APP_WIDTH, APP_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX, SDL_SCALEMODE_NEAREST);
return 0;
}
int SDL_AppEvent(void *appstate, const SDL_Event* event)
{
if (event->type == SDL_EVENT_QUIT)
{
AppContext.app_quit = SDL_TRUE;
}
return 0;
}
int SDL_AppIterate(void *appstate)
{
// convert mouse to "game" coordinates
float mx,my;
SDL_GetMouseState(&mx,&my);
SDL_RenderCoordinatesFromWindow(AppContext.renderer,mx,my,&mx,&my);
plot((int)mx, (int)my, 0xffff);
// random doodle
Uint16 x = rand() % APP_WIDTH;
Uint16 y = rand() % APP_HEIGHT;
plot(x, y, rand());
SDL_RenderClear(AppContext.renderer);
// copy raw buffer to texture
SDL_UpdateTexture(AppContext.fb_texture, NULL, AppContext.buffer, APP_WIDTH * APP_PIXEL_SIZE);
// draw it
SDL_RenderTexture(AppContext.renderer, AppContext.fb_texture, NULL, NULL);
SDL_RenderPresent(AppContext.renderer);
return AppContext.app_quit;
}
void SDL_AppQuit(void* appstate)
{
SDL_free(AppContext.buffer);
SDL_DestroyTexture(AppContext.fb_texture);
SDL_DestroyRenderer(AppContext.renderer);
SDL_DestroyWindow(AppContext.window);
SDL_Quit();
SDL_Log("Application quit successfully!");
}
void plot(Sint16 x, Sint16 y, Uint32 c)
{
if ((x < APP_WIDTH) && (y < APP_HEIGHT))
{
#if (APP_PIXEL_SIZE == 1)
Uint8* ptr = (Uint8*)AppContext.buffer;
ptr[x + (y * APP_WIDTH)] = (Uint8)c;
#endif
#if APP_PIXEL_SIZE == 2
Uint16* ptr = (Uint16*)AppContext.buffer;
ptr[x + (y * APP_WIDTH)] = (Uint16)c;
#endif
#if APP_PIXEL_SIZE == 4
Uint32* ptr = (Uint32*)AppContext.buffer;
ptr[x + (y * APP_WIDTH)] = (Uint32)c;
#endif
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment