Monday, April 6, 2026
How to setup SDL2 lib for Python
SDL 2 (Simple DirectMedia Layer 2) is an open‑source, cross‑platform library that gives programs low‑level access to graphics, audio, input devices, and timing. By handling window creation, 2D rendering, OpenGL/Vulkan contexts, sound playback, keyboard/mouse/controller input, and basic threading, it lets developers write multimedia and game code once and run it on Windows, macOS, Linux, iOS, Android, and many consoles.
Install Ubuntu package:
sudo apt install python3-sdl2
test.py:
import sdl2
version = sdl2.SDL_version()
sdl2.SDL_GetVersion(version)
print(f"SDL2 version: {version.major}.{version.minor}.{version.patch}")
Hello world example:
import sdl2
import sdl2.ext
def run():
sdl2.ext.init()
window = sdl2.ext.Window("Hello SDL2", size=(640, 480))
window.show()
running = True
while running:
events = sdl2.ext.get_events()
for event in events:
if event.type == sdl2.SDL_QUIT:
running = False
break
sdl2.ext.quit()
if __name__ == "__main__":
run()
Example using font and image extensions:
import sdl2
import sdl2.ext
import sdl2.sdlttf as sdlttf
import sdl2.sdlimage as sdlimage
def run():
# Initialise core + extensions
sdl2.ext.init()
sdlttf.TTF_Init()
sdlimage.IMG_Init(sdlimage.IMG_INIT_PNG)
window = sdl2.ext.Window("SDL2 with TTF & Image", size=(800, 600))
window.show()
renderer = sdl2.ext.Renderer(window)
# --- Load a PNG image ---
surface = sdlimage.IMG_Load(b"image.png")
# Create Texture wrapper from SDL_Texture
texture = sdl2.ext.Texture(renderer, surface)
sdl2.SDL_FreeSurface(surface)
# --- Render a TrueType font ---
font = sdlttf.TTF_OpenFont(b"mono.ttf", 48)
fg = sdl2.SDL_Color(255, 255, 255)
text_surface = sdlttf.TTF_RenderUTF8_Blended(font, b"Hello, SDL2!", fg)
text_texture = sdl2.ext.Texture(renderer, text_surface)
sdl2.SDL_FreeSurface(text_surface)
running = True
while running:
for event in sdl2.ext.get_events():
if event.type == sdl2.SDL_QUIT:
running = False
renderer.clear(sdl2.SDL_Color(0, 0, 0))
# draw image - using Texture objects directly
renderer.copy(texture, dstrect=sdl2.SDL_Rect(100, 100, 200, 200))
# draw text
renderer.copy(text_texture, dstrect=sdl2.SDL_Rect(350, 250, 300, 60))
renderer.present()
# Clean up
texture.destroy()
text_texture.destroy()
sdlttf.TTF_CloseFont(font)
sdlttf.TTF_Quit()
sdlimage.IMG_Quit()
sdl2.ext.quit()
if __name__ == "__main__":
run()
Wednesday, March 25, 2026
Generated font in C
/* ── draw a simple bitmap title string (3×5 pixel font, ASCII 32-90) ────────
This tiny font avoids the SDL_ttf dependency entirely. */
static const Uint8 FONT3x5[][5] = {
{0x00,0x00,0x00,0x00,0x00}, /* ' ' */
{0x40,0x40,0x40,0x00,0x40}, /* '!' */
{0xA0,0xA0,0x00,0x00,0x00}, /* '"' */
{0xA0,0xE0,0xA0,0xE0,0xA0}, /* '#' */
{0x60,0xC0,0x60,0xC0,0x60}, /* '$' – placeholder */
{0x80,0x20,0x40,0x80,0x20}, /* '%' – placeholder */
{0x40,0xA0,0x40,0xA0,0xC0}, /* '&' – placeholder */
{0x40,0x40,0x00,0x00,0x00}, /* '\'' */
{0x20,0x40,0x40,0x40,0x20}, /* '(' */
{0x80,0x40,0x40,0x40,0x80}, /* ')' */
{0xA0,0x40,0xE0,0x40,0xA0}, /* '*' */
{0x00,0x40,0xE0,0x40,0x00}, /* '+' */
{0x00,0x00,0x00,0x40,0x80}, /* ',' */
{0x00,0x00,0xE0,0x00,0x00}, /* '-' */
{0x00,0x00,0x00,0x00,0x40}, /* '.' */
{0x20,0x20,0x40,0x80,0x80}, /* '/' */
{0x60,0xA0,0xA0,0xA0,0x60}, /* '0' */
{0x40,0xC0,0x40,0x40,0xE0}, /* '1' */
{0xC0,0x20,0x40,0x80,0xE0}, /* '2' */
{0xC0,0x20,0x40,0x20,0xC0}, /* '3' */
{0xA0,0xA0,0xE0,0x20,0x20}, /* '4' */
{0xE0,0x80,0xC0,0x20,0xC0}, /* '5' */
{0x60,0x80,0xE0,0xA0,0x60}, /* '6' */
{0xE0,0x20,0x40,0x80,0x80}, /* '7' */
{0x60,0xA0,0x60,0xA0,0x60}, /* '8' */
{0x60,0xA0,0x60,0x20,0x60}, /* '9' */
{0x00,0x40,0x00,0x40,0x00}, /* ':' */
{0x00,0x40,0x00,0x40,0x80}, /* ';' */
{0x20,0x40,0x80,0x40,0x20}, /* '<' */
{0x00,0xE0,0x00,0xE0,0x00}, /* '=' */
{0x80,0x40,0x20,0x40,0x80}, /* '>' */
{0xC0,0x20,0x40,0x00,0x40}, /* '?' */
{0x60,0xA0,0xE0,0x80,0x60}, /* '@' – placeholder */
{0x40,0xA0,0xE0,0xA0,0xA0}, /* 'A' */
{0xC0,0xA0,0xC0,0xA0,0xC0}, /* 'B' */
{0x60,0x80,0x80,0x80,0x60}, /* 'C' */
{0xC0,0xA0,0xA0,0xA0,0xC0}, /* 'D' */
{0xE0,0x80,0xC0,0x80,0xE0}, /* 'E' */
{0xE0,0x80,0xC0,0x80,0x80}, /* 'F' */
{0x60,0x80,0xA0,0xA0,0x60}, /* 'G' */
{0xA0,0xA0,0xE0,0xA0,0xA0}, /* 'H' */
{0xE0,0x40,0x40,0x40,0xE0}, /* 'I' */
{0x20,0x20,0x20,0xA0,0x40}, /* 'J' */
{0xA0,0xA0,0xC0,0xA0,0xA0}, /* 'K' */
{0x80,0x80,0x80,0x80,0xE0}, /* 'L' */
{0xA0,0xE0,0xE0,0xA0,0xA0}, /* 'M' */
{0xA0,0xE0,0xE0,0xC0,0xA0}, /* 'N' */
{0x40,0xA0,0xA0,0xA0,0x40}, /* 'O' */
{0xC0,0xA0,0xC0,0x80,0x80}, /* 'P' */
{0x40,0xA0,0xA0,0xC0,0x60}, /* 'Q' */
{0xC0,0xA0,0xC0,0xA0,0xA0}, /* 'R' */
{0x60,0x80,0x40,0x20,0xC0}, /* 'S' */
{0xE0,0x40,0x40,0x40,0x40}, /* 'T' */
{0xA0,0xA0,0xA0,0xA0,0x60}, /* 'U' */
{0xA0,0xA0,0xA0,0x40,0x40}, /* 'V' */
{0xA0,0xA0,0xE0,0xE0,0xA0}, /* 'W' */
{0xA0,0xA0,0x40,0xA0,0xA0}, /* 'X' */
{0xA0,0xA0,0x40,0x40,0x40}, /* 'Y' */
{0xE0,0x20,0x40,0x80,0xE0}, /* 'Z' */
};
This is a tiny 3×5 pixel bitmap font used in games or demos.
It's a very compact way to draw text on screen without using any real font library. Perfect for retro-style games, small tools, or when you want to keep dependencies minimal.
How it works:
• Each character is 3 pixels wide and 5 pixels tall.
• The font covers ASCII characters from space (32) to 'Z' (90).
• Every character is stored as 5 bytes (one byte per row).
• Each byte uses its top 3 bits to represent the 3 pixels of that row (1 = pixel on, 0 = pixel off).
Example for the letter 'A':
{0x40,0xA0,0xE0,0xA0,0xA0}, /* 'A' */
Let's break it down row by row (binary):
Row 0: 0100 0000 → . # . (only middle pixel)
Row 1: 1010 0000 → # . #
Row 2: 1110 0000 → # # #
Row 3: 1010 0000 → # . #
Row 4: 1010 0000 → # . #
ASCII Art Explanation of the whole font concept
Here's a visual of how the 3×5 font renders some common characters:
Space 'A' 'B' 'C' '1' '8'
. . . . # . # # . # # # . # . # # # ← row 0
. . . # . # # . # # . . # # . # . # ← row 1
. . . # # # # # . # . . . # . # # # ← row 2
. . . # . # # . # # . . . # . # . # ← row 3
. . . # . # # # . # # # # # # # # # ← row 4
SDL2 example function
static void draw_char(SDL_Renderer *r, int cx, int cy, char ch, int scale)
{
int idx = (int)ch - 32;
if (idx < 0 || idx >= (int)(sizeof FONT3x5 / sizeof FONT3x5[0])) return;
const Uint8 *glyph = FONT3x5[idx];
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 3; col++) {
if (glyph[row] & (0x80 >> col)) {
SDL_Rect px = { cx + col*scale, cy + row*scale, scale, scale };
SDL_RenderFillRect(r, &px);
}
}
}
}
draw_char(renderer, x, y, 'A', 4);
Monday, March 16, 2026
How to setup C development environment in Windows 11
MSYS2
MSYS2 is a collection of tools and libraries providing you with an easy-to-use environment for building, installing and running native Windows software.
MSYS2 WEBSITE
Terminal
To open terminal run executable at: C:\msys64\mingw64.exe
Package manager
MSYS2 comes with packman package manager that is found in ArchLinux.
First run update:
pacman -Syuu
After that install build tools:
pacman -S --noconfirm mingw-w64-x86_64-toolchain mingw-w64-i686-toolchain
Test to see if GCC is installed by typing:
gcc
Where's my C drive?
To access C drive type: .
cd /c/
Windows example
Create main.c with this content:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShow) {
MessageBoxW(NULL, L"Hello, Win32!", L"Demo", MB_OK);
return 0;
}
Compile the code with this command:
gcc -o hello_win.exe main.c -lmingw32 -lgdi32 -luser32
Thursday, February 26, 2026
Rendering graphics on Linux with SDL2
Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D. It is used by video playback software, emulators, and popular games including Valve's award winning catalog and many Humble Bundle games.
SDL officially supports Windows, macOS, Linux, iOS, and Android. Support for other platforms may be found in the source code.
Developing on Ubuntu/Debian
sudo apt update
sudo apt install build-essential pkg-config
sudo apt install libsdl2-dev
## common addons
sudo apt install libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libsdl2-net-dev
## OpenGL
sudo apt install libgl1-mesa-dev
Basic example
//main.c
#include <SDL2/SDL.h> // SDL main header (types, functions, constants)
#include <stdbool.h> // for bool, true, false
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
int main(int argc, char* argv[]) {
// Initialize SDL video subsystem. SDL_Init returns 0 on success.
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError()); // log SDL error
return 1;
}
// Create an SDL window centered on the screen with the defined size.
SDL_Window* window = SDL_CreateWindow(
"Blank SDL2 Window", // window title
SDL_WINDOWPOS_CENTERED, // x position
SDL_WINDOWPOS_CENTERED, // y position
WINDOW_WIDTH, // width
WINDOW_HEIGHT, // height
SDL_WINDOW_SHOWN // window flags (visible)
);
// Check window creation success.
if (!window) {
SDL_Log("Failed to create window: %s", SDL_GetError());
SDL_Quit(); // clean up SDL subsystems
return 1;
}
// Create a renderer for the window. -1 chooses the first available driver.
// SDL_RENDERER_ACCELERATED requests hardware acceleration.
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
SDL_Log("Failed to create renderer: %s", SDL_GetError());
SDL_DestroyWindow(window); // destroy window before quitting
SDL_Quit();
return 1;
}
bool running = true; // main loop flag
SDL_Event event; // event container
// Main loop: handle events, clear and present the screen, throttle frame rate.
while (running) {
// Process all pending events.
while (SDL_PollEvent(&event)) {
// If window close or any key pressed, exit loop.
if (event.type == SDL_QUIT ||
(event.type == SDL_KEYDOWN)) {
running = false;
}
}
// Set draw color to opaque black (r,g,b,a) and clear the render target.
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// Present the backbuffer to the screen.
SDL_RenderPresent(renderer);
// Simple frame cap: delay ~16 ms -> ~60 FPS.
SDL_Delay(16);
}
// Clean up resources in reverse creation order.
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
// Print the name of the video driver SDL used (useful for debugging).
printf("Video driver: %s\n", SDL_GetCurrentVideoDriver());
return 0;
}
Build command
gcc -o main main.c -lSDL2
Draw rectangle
// gcc -o main main.c -lSDL2
#include <SDL2/SDL.h>
#include <stdbool.h>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
// Helper function: draw a filled rectangle using top-left coordinates
void draw_rect(SDL_Renderer* renderer, SDL_Color color, int x, int y, int w, int h) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_Rect rect = { x, y, w, h };
SDL_RenderFillRect(renderer, &rect);
}
// Draw 1px outline + X connecting all corners
void draw_rect_outline(SDL_Renderer* renderer, SDL_Color color, int x, int y, int w, int h) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
// Outline: draw 4 lines (top, bottom, left, right) — 1px thick
// Top edge
SDL_RenderDrawLine(renderer, x, y, x + w - 1, y);
// Bottom edge
SDL_RenderDrawLine(renderer, x, y + h - 1, x + w - 1, y + h - 1);
// Left edge
SDL_RenderDrawLine(renderer, x, y, x, y + h - 1);
// Right edge
SDL_RenderDrawLine(renderer, x + w - 1, y, x + w - 1, y + h - 1);
// Diagonal "X": connect opposite corners
SDL_RenderDrawLine(renderer, x, y, x + w - 1, y + h - 1); // top-left to bottom-right
SDL_RenderDrawLine(renderer, x + w - 1, y, x, y + h - 1); // top-right to bottom-left
}
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
SDL_Window* window = SDL_CreateWindow(
"Rectangle SDL2 Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH,
WINDOW_HEIGHT,
SDL_WINDOW_SHOWN
);
if (!window) {
SDL_Log("Failed to create window: %s", SDL_GetError());
SDL_Quit();
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
SDL_Log("Failed to create renderer: %s", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
bool running = true;
SDL_Event event;
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN) {
running = false;
}
}
// Clear screen to black
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// Example: draw a red rectangle at (100, 50) with size 200x100
SDL_Color red = {255, 0, 0, 255};
draw_rect(renderer, red, 100, 50, 200, 100);
// Example: draw a semi-transparent green square
SDL_Color green = {0, 255, 0, 128};
draw_rect(renderer, green, 300, 200, 80, 80);
SDL_RenderPresent(renderer);
SDL_Delay(16); // ~60 FPS
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Saturday, January 10, 2026
Visualize C code
CFLOW
GNU cflow analyzes a collection of C source files and prints a graph, charting control flow within the program.
GRAPHVIZ
Graphviz is open source graph visualization software. Graph visualization is a way of representing structural information as diagrams of abstract graphs and networks. It has important applications in networking, bioinformatics, software engineering, database and web design, machine learning, and in visual interfaces for other technical domains.
Ubuntu/debian install
sudo apt-get install cflow graphviz
Generate "callgraph.dot" (text file that image renderer will use)
#run this in project dir
cflow $(find . -name "*.c" -o -name "*.h") --format=dot > callgraph.dot
Render to PNG
# fdp (force-directed placement)
fdp -Tpng callgraph.dot -o callgraph.png
# circo (circular layout)
circo -Tpng callgraph.dot -o callgraph.png
# neato
neato -Tpng callgraph.dot -o callgraph.png
Result
To get SVG output use:
fdp -Tsvg callgraph.dot -o callgraph.svg
circo -Tsvg callgraph.dot -o callgraph.svg
neato -Tsvg callgraph.dot -o callgraph.svg
Friday, January 9, 2026
Compile C project to single text file for AI analysis.
Simple script that collects all your .h/.c files and adds project path before collected text - and ads them to single text file that you can then give to AI for analysis. Add script to you project root.
#!/usr/bin/env bash
# combine_sources.sh
# Creates a single text file (combined.txt) that contains the contents of every
# .c and .h file in the project, prefixed by a comment showing its path.
# Exit on any error
set -e
# Output file placed in the directory where this script lives (project root)
output="$(dirname "$0")/combined.txt"
> "$output" # truncate/create the file
# Find all .c and .h files under the project root (excluding the script itself)
find "$(dirname "$0")" -type f \( -name "*.c" -o -name "*.h" \) ! -name "$(basename "$0")" |
while IFS= read -r file; do
# Write a header comment with the relative path
echo "# $file" >> "$output"
# Append the file's contents
cat "$file" >> "$output"
# Add a blank line between files for readability
echo "" >> "$output"
done
echo "All source files have been combined into $output"
Saturday, January 3, 2026
stdint cheatsheet
| Category |
Type Name |
Description |
| Exact-width | int8_t | 8-bit signed integer |
uint8_t | 8-bit unsigned integer |
int16_t | 16-bit signed integer |
uint16_t | 16-bit unsigned integer |
int32_t | 32-bit signed integer |
uint32_t | 32-bit unsigned integer |
int64_t | 64-bit signed integer |
uint64_t | 64-bit unsigned integer |
| Minimum-width | int_least8_t | Signed int with at least 8 bits |
uint_least8_t | Unsigned int with at least 8 bits |
int_least16_t | Signed int with at least 16 bits |
uint_least16_t | Unsigned int with at least 16 bits |
int_least32_t | Signed int with at least 32 bits |
uint_least32_t | Unsigned int with at least 32 bits |
int_least64_t | Signed int with at least 64 bits |
uint_least64_t | Unsigned int with at least 64 bits |
| Fastest minimum-width | int_fast8_t | Fastest signed int with at least 8 bits |
uint_fast8_t | Fastest unsigned int with at least 8 bits |
int_fast16_t | Fastest signed int with at least 16 bits |
uint_fast16_t | Fastest unsigned int with at least 16 bits |
int_fast32_t | Fastest signed int with at least 32 bits |
uint_fast32_t | Fastest unsigned int with at least 32 bits |
int_fast64_t | Fastest signed int with at least 64 bits |
uint_fast64_t | Fastest unsigned int with at least 64 bits |
| Pointer-holding | intptr_t | Signed integer capable of holding a void pointer |
uintptr_t | Unsigned integer capable of holding a void pointer |
| Greatest-width | intmax_t | Maximum-width signed integer type |
| uintmax_t | Maximum-width unsigned integer type |