# m2SDL3 — SDL3 bindings for GNU Modula-2 Thin `DEFINITION MODULE FOR "C"` bindings of SDL 3.4 for `gm2` (GCC 16 / GNU Modula-2), covering init, video, version, timer, error, events and the 2D renderer starter subset. Upstream sources live in `SDL-release-3.4.16/` (read-only reference, never modified by this binding; per its `AGENTS.md` no AI-generated code is contributed upstream). All binding code below is original work that only *uses* SDL headers at compile time and links the prebuilt `SDL-release-3.4.16/build/libSDL3.so`. ## Status Starter set, verified with gm2 + SDL 3.4.16 on Linux: | Module | C header | Contents | |---|---|---| | `SDL3` | ``, ``, `` | init/quit (`BOOLEAN` returns), `GetError`, `Delay`/`DelayNS`, 64-bit ticks, performance counter | | `SDL3Version` | `` | `SDL_GetVersion(): INTEGER` versionnum, `GetRevision` | | `SDL3Video` | `` | window create/destroy, title, size/position, show/hide, flags (`LONGCARD`) | | `SDL3Events` | `` | `PumpEvents`, `PollEvent`, `WaitEvent`, `WaitEventTimeout`, `PushEvent`, `HasEvent(s)` (`BOOLEAN`), quit/key/mouse + window-close constants, 128-byte buffer | | `SDL3Rect` | `` | pure-M2 `SDLPoint`/`SDLFPoint`/`SDLRect`/`SDLFRect` + helpers (`SHORTREAL` = C float) | | `SDL3Render` | `` | window+renderer creation, draw color (+float), logical presentation, clear/present, points/lines/rects (float `SDLFRect`), render scale, output size, debug text | | `SDL3Key` | `` | pure-M2 keycode constants (arrows, Q/R, Escape...) | | `SDL3Stdinc` | `` | `malloc`/`calloc`/`free` (frees SDL-allocated strings) | | `SDL3Filesystem` | `` | base/pref/user-folder/cwd paths, mkdir/remove/rename/copy (no callbacks) | | `SDL3Power` | `` | `GetPowerInfo` state + seconds/percent | | `SDL3Locale` | `` | preferred-locales list (`SDLLocale` records) | | `SDL3Clipboard` | `` | plain-text set/get/has (+primary selection; no MIME callbacks) | | `SDL3Utils` (`lib/`) | — | `CStrToM2()` + `GetErrorString()`, version decode, `DrainEvents()` quit pump (QUIT + WINDOW_CLOSE_REQUESTED), `PollM2Event()` decoded poll (keycode at offset 28) | ## Layout ```text m2SDL3/ src/ FOR "C" .def bindings (+ pure-M2 SDL3Rect/SDL3Key) lib/ pure-M2 helpers built on the bindings (SDL3Utils) tests/ gm2 smoke tests + run_tests.sh examples/ hello_window, version, event_loop, renderer_demo showcases/ clear, primitives, lines, points, rectangles, debug_text, snake build/ generated binaries (git-ignored) SDL-release-3.4.16/ upstream SDL reference + prebuilt lib (untouched) ``` ## Prerequisites - `gm2` (tested: 16.0.1 experimental, `~/bin/Modula2/Gm2/bin/gm2`) - SDL 3.4.16 already built at `SDL-release-3.4.16/build/libSDL3.so` (headers at `SDL-release-3.4.16/include`) ```sh export PATH=$HOME/bin/Modula2/Gm2/bin:$PATH ``` ## Build & test ```sh make # tests + examples + showcases -> build/ ./tests/run_tests.sh SDL_VIDEODRIVER=dummy ./tests/run_tests.sh # headless ./build/examples/hello_window ./build/examples/version ./build/examples/event_loop ./build/examples/renderer_demo ./build/showcases/showcase_clear # or rectangles / primitives / snake ``` `make check` is `make tests` + the runner script. ## Usage ```modula2 FROM SDL3 IMPORT SDL_Init, SDL_Quit, SDLInitVideo; FROM SDL3Video IMPORT SDL_CreateWindow, SDL_DestroyWindow, WindowHidden; ``` Compile your program with the binding search path and the C library: ```sh gm2 -Isrc -Ilib \ -ISDL-release-3.4.16/include \ myprog.mod src/SDL3Rect.mod lib/SDL3Utils.mod src/SDL3Key.mod \ -o myprog -LSDL-release-3.4.16/build -lSDL3 \ -Wl,-rpath,$PWD/SDL-release-3.4.16/build ``` Notes: - SDL3 `bool` <-> `BOOLEAN` (see gm2 "Elementary data types" node); init/video/event/render calls return `[ BOOLEAN ]` (ignorable): `IF NOT SDL_Init(...) THEN` or `SDL_RenderClear(ren);`. - `CARDINAL <-> Uint32`, `LONGCARD <-> Uint64`, `INTEGER <-> int` (window flags are 64-bit: pass `VAL(LONGCARD, WindowResizable)`). - `SHORTREAL <-> float` (`SDL_FRect`/`SDL_FPoint` fields, draw coordinates, `SetRenderDrawColorFloat`); `REAL <-> double`. - Opaque `SDL_Window *` / `SDL_Renderer *` / `char *` travel as `ADDRESS` (`NIL` == failure / default driver). - `ARRAY OF CHAR` parameters map onto `char *`: string literals and `CHAR` arrays can be passed directly (see gm2 "Interface to C" node). - `VAR` record parameters map onto `T *`: `SDL_GetWindowSize(win,w,h)`, `SDL_RenderFillRect(ren, rect)`. - `SDL_GetTicks()` is now `LONGCARD` milliseconds; `SDL_GetVersion()` returns an `INTEGER` versionnum (`VersionMajor/Minor/Micro` decode it). - Closing a window yields `EventWindowCloseRequested` (0210H) as well as `EventQuit`; `DrainEvents`/`PollM2Event` treat both as `evQuit`. ## SDL2 -> SDL3 porting cheatsheet | SDL2 binding | SDL3 binding | |---|---| | `SDL_Init(): INTEGER`, `rc # 0` | `SDL_Init(): [ BOOLEAN ]`, `NOT ...` / `= FALSE` | | `CreateWindow(t,x,y,w,h,flags: CARDINAL)` | `CreateWindow(t,w,h,flags: LONGCARD)` | | `GetTicks(): CARDINAL` + `GetTicks64()` | `GetTicks(): LONGCARD` (ms), `GetTicksNS()` (ns) | | `GetVersion(VAR v)` record | `GetVersion(): INTEGER` + `VersionMajor/Minor/Micro` | | `RenderDrawPoint/Line/Rect` (int) | `RenderPoint/Line/Rect` (`SHORTREAL`/`SDLFRect`) | | `RenderSetLogicalSize(w,h)` | `SetRenderLogicalPresentation(w,h,mode)` | | `EventBufferBytes = 56`, sym at 20 | `EventBufferBytes = 128`, key at 28, close-request = quit | ## Roadmap 1. Texture/surface subset (`SDL_Texture`, `SDL_Surface` load/blit). 2. Audio stream subset (`SDL_AudioStream`, device open). 3. Gamepad/joystick subset. 4. Full `SDL_Event` variant record (keyboard/mouse/window typed).