News:

Download Pelles C here: http://www.pellesc.se

Main Menu

Recent posts

#11
Bug reports / Re: stdckdint.h bug report
Last post by TimoVJL - Yesterday at 03:10:42 PM
https://cppreference.net/c/numeric/ckd_mul.html

Just easier to read:
#include <stdio.h>
#include <stdckdint.h>
char *ab[] = {"false", "true "};
int main(void)
{
    long int a = 655350;
    long int b = 655350;//10
    int c = 0;
    bool result;
    result = ckd_mul(&c, a, b); // ckd_add(&c, a, b); ckd_sub(&c, a, b);
    printf("result: %s c = %d\n", ab[result], c);

    result =  ckd_add(&c, a, b); // ckd_sub(&c, a, b);
    printf("result: %s c = %d\n", ab[result], c);

    result = ckd_sub(&c, a, b);
    printf("result: %s c = %d\n", ab[result], c);
    return 0;
}
#12
Bug reports / Re: stdckdint.h bug report
Last post by John Z - Yesterday at 10:13:46 AM
Hi Ander,

Well not always - If the numbers are big enough to 'wrap' you'll get 'true'
for example - output from code below :
true
c = -13107100
false
c = 1310700
false
c = 0
Press any key to continue...
#include <stdio.h>
#include <stdckdint.h>
int main(void)
{
    long int a = 655350;
    long int b = 655350;//10
    int c = 0;
    //int c = 0;
    bool result = true;
    result = ckd_mul(&c, a, b); // ckd_add(&c, a, b); ckd_sub(&c, a, b);
    if (result == true) {
        puts("true\n");
    }else{
        puts("false\n");
    }
    printf("c = %d\n", c);   
    result =  ckd_add(&c, a, b); // ckd_sub(&c, a, b);
    if (result == true) {
        puts("true\n");
    }else{
        puts("false\n");
    }
    printf("c = %d\n", c);
    result = ckd_sub(&c, a, b);
    if (result == true) {
        puts("true\n");
    }else{
        puts("false\n");
    }
    printf("c = %d\n", c);
    return 0;
}

Cheers,
John Z
#13
Graphics programming / Re: raylib 5.5 + PellesC v13.0...
Last post by rweidner - March 06, 2026, 08:48:41 PM
Quote from: TimoVJL on March 04, 2026, 05:19:10 PMThose libraries needs a RAD environment too to survive.
Just think what happened to Borland RADs.

Small programs are easy to develop with basic Win32 GUI.

Hi TimoVJL,

I agree with you - libraries tend to survive longer when they have a good RAD story around them, and Win32 GUI work can still be very productive with the right tools.

For context on why I am writing this raylib + PellesC tutorial: I am actively working on a 2D game in C using raylib right now. Once I finish it, I plan to do a couple of ports:

* Port 1: GDI + Win32 API (including input and sound)
* Port 2: Direct2D + Win32 API

Those ports are mostly for me: they are a learning project, and also an excuse to explore and document programming techniques. I enjoy writing tutorials, so I am trying to capture the "gotchas" and the practical setup steps as I find them.

Thanks again for chiming in on the thread.

Ronald
#14
Graphics programming / Re: raylib 5.5 + PellesC v13.0...
Last post by rapte - March 06, 2026, 04:28:21 PM
Thanks for the explanation :)
#15
Graphics programming / Re: raylib 5.5 + PellesC v13.0...
Last post by rweidner - March 06, 2026, 03:25:21 PM
The problem is that in C23 bool is a keyword.  What's happening here in the raylib.h on line 210 is:

// Boolean type
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
    #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool)
    typedef enum bool { false = 0, true = !false } bool;
    #define RL_BOOL_TYPE
#endif

The developer is trying to define bool. There are fixes for this. The primary one is to fix the header and submit a pull request to the raylib project. But, I didn't go that route, yet. Instead, I changed to C17 and kept moving.
#16
Graphics programming / Re: raylib 5.5 + PellesC v13.0...
Last post by rapte - March 06, 2026, 02:27:50 PM
Thank you rweidner and Vortex for the detailed steps and examples on how to get raylib working with Pelles C.

I got the example working for both 32-bit and 64-bit and it works with c99, c11 and c17, but gives the following error with c23

Building main.obj.
C:\SDK\raylib-5.5\include\raylib.h(210): warning #2090: Missing enum tag.
C:\SDK\raylib-5.5\include\raylib.h(210): error #2002: Invalid combination of 'enum' and 'bool'.
C:\SDK\raylib-5.5\include\raylib.h(210): warning #2014: Empty declaration.
C:\SDK\raylib-5.5\include\raylib.h(210): error #2001: Syntax error: expected ';' but found '{'.
C:\SDK\raylib-5.5\include\raylib.h(210): error #2156: Unrecognized declaration.
C:\SDK\raylib-5.5\include\raylib.h(210): warning #2014: Empty declaration.

#17
Graphics programming / Re: raylib 5.5 + PellesC v13.0...
Last post by Vortex - March 05, 2026, 08:15:27 PM
Thanks, I managed to build the project without game_main.h  Here is a modified version :

Main project file :

#pragma comment(lib, "raylibdll.lib")

extern void raylibProc(void);

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    raylibProc();
    return 0;
}

Second module :

#include "raylib.h"

void raylibProc(void)
{
SetTraceLogLevel(LOG_NONE);
    InitWindow(800, 450, "raylib hello");
    SetTargetFPS(60);

    while (!WindowShouldClose())
    {
        BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawText("Hello, raylib!", 190, 200, 40, BLACK);
        EndDrawing();
    }

    CloseWindow();
}

Default calling Convention : __cdecl
#18
Graphics programming / A GDI Double Buffered Example
Last post by rweidner - March 05, 2026, 05:04:36 AM
A GDI Double-Buffered Example (Pelles C)

Note: This is not meant to be a GDI32 programming tutorial. I am not an expert in GDI32 (yet), so I probably should not try to write a tutorial on it right now. :)

Instead, this is a one-file example intended to show a working GDI double-buffered program in Pelles C v13.00.9. It may also be useful to some people as a small foundation for GDI32 experiments.

Prereq (how I tested it)

I used the Windows SDK on my machine.

If you already have it installed, it is usually somewhere under:

C:\Program Files (x86)\Windows Kits

The one I am using specifically is here:

 C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x86  (libs)
 C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um  (headers/includes)

If you do not have the Windows SDK, start here:

https://learn.microsoft.com/en-us/windows/apps/windows-sdk/

Side note: If you have Visual Studio / Build Tools installed, the Windows SDK may already be installed with it.


To compile in Pelles C

1. Create a new Win32 GUI Project (this example uses WinMain, not main)
2. Open Project -> Project Options
3. Click General -> Folders
4. Notice the drop-down menu that probably says Libraries
5. Add the path to the SDK library folder (under Windows Kits)
6. Change the drop-down menu to Includes
7. Add the path to the SDK include folder (under Windows Kits)
8. Create main.c
9. Paste the code below

Code (main.c)

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

static const char g_szClassName[] = "WinGdiHelloBackbufferedClass";

static int   g_running = 1;
static HFONT g_font = NULL;

/* Backbuffer objects */
static HDC     g_backDC = NULL;
static HBITMAP g_backBmp = NULL;
static HBITMAP g_backOldBmp = NULL;
static int     g_backW = 0;
static int     g_backH = 0;

static void DestroyBackbuffer(void)
{
    if (g_backDC)
    {
        if (g_backOldBmp)
        {
            SelectObject(g_backDC, g_backOldBmp);
            g_backOldBmp = NULL;
        }

        if (g_backBmp)
        {
            DeleteObject(g_backBmp);
            g_backBmp = NULL;
        }

        DeleteDC(g_backDC);
        g_backDC = NULL;
    }

    g_backW = 0;
    g_backH = 0;
}

static int EnsureBackbuffer(HWND hwnd, int w, int h)
{
    HDC hdcWindow;
    HBITMAP newBmp;

    if (w <= 0 || h <= 0)
        return 0;

    if (g_backDC && g_backBmp && g_backW == w && g_backH == h)
        return 1;

    DestroyBackbuffer();

    hdcWindow = GetDC(hwnd);
    if (!hdcWindow)
        return 0;

    g_backDC = CreateCompatibleDC(hdcWindow);
    if (!g_backDC)
    {
        ReleaseDC(hwnd, hdcWindow);
        return 0;
    }

    newBmp = CreateCompatibleBitmap(hdcWindow, w, h);
    ReleaseDC(hwnd, hdcWindow);

    if (!newBmp)
    {
        DeleteDC(g_backDC);
        g_backDC = NULL;
        return 0;
    }

    g_backBmp = newBmp;
    g_backOldBmp = (HBITMAP)SelectObject(g_backDC, g_backBmp);
    g_backW = w;
    g_backH = h;

    return 1;
}

static void RenderSceneToBackbuffer(HWND hwnd)
{
    RECT rc;
    RECT textRc;
    HBRUSH whiteBrush;

    GetClientRect(hwnd, &rc);

    if (!EnsureBackbuffer(hwnd, rc.right - rc.left, rc.bottom - rc.top))
        return;

    whiteBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
    FillRect(g_backDC, &rc, whiteBrush);

    SetBkMode(g_backDC, TRANSPARENT);
    SetTextColor(g_backDC, RGB(0, 0, 0));

    if (g_font)
        SelectObject(g_backDC, g_font);

    SetRect(&textRc, 190, 200, rc.right, rc.bottom);
    DrawTextA(g_backDC, "Hello, GDI Backbuffer!", -1, &textRc, DT_LEFT | DT_TOP | DT_SINGLELINE);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
        g_font = CreateFontA(
            -40, 0, 0, 0, FW_NORMAL,
            FALSE, FALSE, FALSE,
            ANSI_CHARSET, OUT_DEFAULT_PRECIS,
            CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
            DEFAULT_PITCH | FF_DONTCARE,
            "Arial"
        );
        return 0;

    case WM_SIZE:
    {
        int w = LOWORD(lParam);
        int h = HIWORD(lParam);
        EnsureBackbuffer(hwnd, w, h);
        return 0;
    }

    case WM_ERASEBKGND:
        /* We paint the full frame ourselves from a backbuffer. Prevent default erase flicker. */
        return 1;

    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
        {
            DestroyWindow(hwnd);
            return 0;
        }
        break;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        RenderSceneToBackbuffer(hwnd);

        if (g_backDC && g_backBmp)
        {
            BitBlt(
                hdc,
                0, 0, g_backW, g_backH,
                g_backDC,
                0, 0,
                SRCCOPY
            );
        }

        EndPaint(hwnd, &ps);
        return 0;
    }

    case WM_DESTROY:
        DestroyBackbuffer();

        if (g_font)
        {
            DeleteObject(g_font);
            g_font = NULL;
        }

        g_running = 0;
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProcA(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSA wc;
    HWND hwnd;
    RECT wr;
    MSG msg;
    DWORD frameMs = 1000 / 60;
    DWORD lastTick = GetTickCount();

    (void)hPrevInstance;
    (void)lpCmdLine;

    ZeroMemory(&wc, sizeof(wc));
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = hInstance;
    wc.lpszClassName = g_szClassName;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = NULL; /* no default brush; we fully repaint */

    if (!RegisterClassA(&wc))
        return 1;

    wr.left = 0;
    wr.top = 0;
    wr.right = 800;
    wr.bottom = 450;
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

    hwnd = CreateWindowExA(
        0,
        g_szClassName,
        "GDI backbuffer hello",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        wr.right - wr.left,
        wr.bottom - wr.top,
        NULL, NULL, hInstance, NULL
    );

    if (!hwnd)
        return 1;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (g_running)
    {
        while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                g_running = 0;
                break;
            }
            TranslateMessage(&msg);
            DispatchMessageA(&msg);
        }

        if (!g_running)
            break;

        if ((GetTickCount() - lastTick) >= frameMs)
        {
            lastTick = GetTickCount();

            /* Trigger one frame render */
            InvalidateRect(hwnd, NULL, FALSE); /* FALSE: do not erase background */
            UpdateWindow(hwnd);
        }
        else
        {
            Sleep(1);
        }
    }

    return 0;
}

If I missed a Pelles C option/setting that matters, let me know and I will update this post.
#19
Bug reports / stdckdint.h bug report
Last post by ander_cc - March 05, 2026, 02:59:33 AM
Yesterday,I learn some c23 new features. Maybe there is a bug in stdckdint.h.

bool ckd_add( type1 *result, type2 a, type3 b );
bool ckd_sub( type1 *result, type2 a, type3 b );
bool ckd_mul( type1 *result, type2 a, type3 b );

Macros always return false. Pelles c 13.01. Windows 11 Simplified Chinese.

#include <stdio.h>
#include <stdckdint.h>
int main(void)
{
int a = 655350;
int b = 10;
short int c = 0;
//int c = 0;
bool result = true;
result = ckd_mul(&c, a, b); // ckd_add(&c, a, b); ckd_sub(&c, a, b);
if (result == true) {
puts("true\n");
}else{
puts("false\n");
}
printf("c = %d\n", c);
return 0;
}
#20
General discussion / Re: Compiling using pomake
Last post by rweidner - March 05, 2026, 02:48:18 AM
It took me a long minute to understand what you're building. You're building a replacement process for managing projects and project configuration. You're doing so with the intention of making the whole process less manual, scriptable, and easier to control. If I understand what you're doing, brilliant.