Skip to content

Working SDL3 clients (linux, windows) - #89

Open
jezek wants to merge 1 commit into
TomenetGame:masterfrom
jezek:sdl3
Open

Working SDL3 clients (linux, windows)#89
jezek wants to merge 1 commit into
TomenetGame:masterfrom
jezek:sdl3

Conversation

@jezek

@jezek jezek commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

SDL3 clients

hello, this is a bigger one... i present you a working sdl3 client for linux & windows (windows client is compiled & tested trough mingw/wine only)

Why?

i think it is annoying whenever making some changes in graphics to implement it for linux & windows separately... sdl3 is multi-platform so the same code is for linux and windows client... and not only for graphics... i made it so, that all the code (net, snd, ...), except for some one-liner macros, is the same... no external dependencies

Highlights

  • both SDL3 linux & windows client share the same code and can be build in parallel without affecting each other (windows client does not need wine to build)
  • no external dependencies, uses compiled in libraries with automatic detection at build time
  • separate user and game directory with fallback to game dir
  • graphics preferences can be previewed and changed in-game without restart and client can be drawn with or without window decorations (can be set in config an in game on the fly)
  • changing tile masks from bg, fg, transparency to bg, fg, outline, with automatic outline generation if set (more in docs) and drawing functions are made so we can have more masks per tile and more tiles per coordinate in future
  • github CI/CD with building release assets (server & x11, win, sdl2 linux/win clients) with info on how to build localy via distrobox... see https://github.com/jezek/tomenet/releases/tag/v4.9.3.0.2.0 and https://github.com/jezek/tomenet/actions
  • the releases archives are packaged with all the .so/.dll files, so no packages are needed to install to run

Caveats

  • libarchive doesn't support 7z with password... i've implemented classical zips with passwords and tar archives
  • sdl3-net does not support getting MAC address... i've implemented fake MAC address creation depending on OS specs (should be the same on the same OS and user)
  • linux client runs on x11 by default (with fallback to wayland), cause wayland does not move windows to requested positions (for now)... although if you wish to run the linux client under wayland , run with SDL_VIDEODRIVER=wayland environment variable

What next?

  • testing and fixing bugs before adoption to releases... i've tried to implement everything what is in the x11/win clients and i tried to test it thoroughly, but mistakes can always happen... if there is anything that needs to be fixed or changed, ping me, i'll try to do my best
  • after adopting, reviewing and releasing these clients, we should deprecate native x11 & windows clients to not end up like this
  • porting the SDL3 client to iOS and android and make it compile under windows (if necessary)... i don't have ios, android nor windows devices at home, so i can't really help with this
  • optimizing tiles & subtiles in-memory images... now when loading tiles/subtiles, all images and layers are stored in memory as big as the underlying bitmaps... the subtiles also use large arrays which need to be traversed often... my idea is to move individual used tiles & subtiles into one synthetic compact image on load before splitting the image into layers... this should drastically reduce memory consumption when using tiles with subtiles... i will try to do this after this is merged

@jezek

jezek commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

for those who like to read, here is more exhausting list with differences from native x11 client

  • To make checking guide checksums OS agnostic, checks aren't hanled by external programs (wget,...), but checked internally using curl & openssl libraries. [client/c-files.c, SDL3_CURL_SSL]

  • There are two storage folders SDL3_GAME_PATH and SDL3_USER_PATH, filled by SDL_GetBasePath, resp. SDL_GetPrefPath. The SDL3_USER_PATH can be overriden by TOMENET_SDL3_USER_PATH environment variable. [client/client.c]

  • Default config file for sdl client is called tomenet.cfg and resides in SDL3 preferences path (SDL3_USER_PATH). [client/client.c, common/externs.h, tomenet.cfg]

  • The executable directory is stored at SDL3_GAME_PATH [common/externs.h]

  • Rewrote part of read_mangrc(...) function to get rid of the goto command. Please don't use goto, it's a bad habit. [client/client.c]

  • Using SDL3_PATH_SEP as separator instead of PATH_SEP. The SDL3_PATH_SEP is taken from the last chararacter of SDL3_GAME_PATH [client/client.c, common/externs.h]

  • Using temp directory in SDL3 preferences location as default [common/common.c]

  • Added OS_SUB_SDL3 (4) & OS_SUB_GCU_SDL3 (5) constant and using in VERSION_OS for SDL3 client [common/defines.h]

  • On server side, added the OS_SUB_SDL3 and OS_SUB_GCU_SDL3 to player os version checking. [server/cmd4.c]

  • Replaced __MINGW32__ macro with MINGW macro

  • SDL3 client uses common/net-sdl3.c for networking, which uses SDL3/SDL_net.h and is OS independent. Currently networking functions necessary only for client are implemented. [common/nes-sdl3.c, common/net-sdl3.h, common/h-net.h]

  • Fix macros indenting in [h-config.h, common/h-net.h, common/sockbuf.c]

  • New makefile.sdl3 for buiding the SDL3 client. Both linux and windows (mingw) version, using -MMD and .d files for dependency tracking.

  • Masks colors for graphics tiles are now defined in the graphics tiles preferences file. [client/c-files.c, m:<num>:<hexRGB>]

  • Introducing maximum number of masks per tile GRAPHICS_MAX_MPT and tiles per coordinate GRAPHICS_MAX_TPC. [common/defines-features.h]

  • Hid #define UG_2MASK 2 into #ifdef GRAPHICS_BG_MASK. UG_2MASK makes no sense outside of GRAPHICS_BG_MASK. [common/defines-features.h]

  • Client can load PCF and TTF fonts. The size of an TTF font is extracted from font name in config "<font_name> " (eg. "Term-Main_Font Hack-Regular.ttf 12"). Fonts are loaded from lib/xtra/font. [client/main-sdl3.c]

  • Client can be run with or without window decorations and can be set in config and changed in window flags menu during game.

  • There is a tiles preview in in-game graphics menu when in bigscreen. [client/c-util.c]

  • New graphicsForceOutline option in tomenet.cfg. If in 2-mask graphics mode and option is set to 0 or more, it makes an outline of set width around tile automaticaly. It is for using bitmaps with only fg/bg masks in 2-mask mode with outline, or ignoring preset outline in fg/bg/bg2 mask images and making a new one with intended width. [client/main-sdl3.c]

  • All changes to graphics tiles in ingame graphics menu can be applied on-the-fly, without restarting client. [client/c-util.c]

  • SDL3 library key handling is not accounting for sticky keys. For me it's an essential thing, so I made a sticky keys emulation. Activating sticky keys can be configured in makefile by setting the SDL3_STICKY_KEYS flag. Stickiness is indicated by changing border color of main window.

  • In makefile.sdl3 renamed w_play to w_player, to match the name of player.pre file and use fewer rules for the .pkg and .c files generation from the .pre files.

  • Copied client/snd-sdl.c to client/snd-sdl3.c, removed WINDOWS macros and changed to SOUND_SDL3 and forced to include SDL3 headers. In makefile.sdl3 using only the snd-sdl3.c and SOUND_SDL3 flag. Changed all other #ifdef SOUND_SDL to work with SOUND_SDL3 too. [client/snd-sdl3.c]

  • Removed file descriptor probing, descriptors are not needed in SDL3, cause samples & music is loaded into memory. So changed the music code, to not load all music files into memory, but load them on the fly (caching last song). [client/snd-sdl3.c]

  • For extracting 7zip archives, client uses libarchive, so no external program is needed.

  • All the ANGBAND_DIR_ variables use absolute paths.

  • Opening urls and files is handled bu SDL_OpenURL function.

  • Add ANGBAND_USER_DIR and ANGBAND_USER_DIR_(USER, SCPT, ...) variables pointing to user storage inside SDL3_USER_PATH.

  • Use user storage to write all files. When reading, try user storage first, then fallback to game storage. This is handled mainly in my_fopen fuction (thus rewrites were made to use my_fopen instead fopen).

  • Installing sound and music packs is made from game dir or user storage and to user storage.

  • Use user dir when saving sound/music.cfg files

  • Search for samples and songs in user dir first

  • Fixes to jukebox, saving, preview and state after force_disabled was introduced.

  • Macro, font and tileset file scanning is done in user and game storage.

  • Differentiating between Backspace and Delete key (unlike POSIX clients). Delete is '\177' or 0x7F now.

  • In knowledge menu, open last screenshot instead of conversion

  • Create fake but deterministic MAC depending on PC stats

  • Added github CI and release creation + local distrobox init, build and release scripts for server, sdl3 clients (linux + win), x11 client and windows client.

  • Default scaling mode is NEAREST for sdl3 clients

  • Startup logo is graphic only when all used solid tiles are loaded (.prf is loaded before logo is drawn)

@mhirki

mhirki commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Thanks for continuing to work on the SDL client.

I tested the SDL3 client on Windows and it appears to have a new bug: it does not respect the UI scaling factor. My laptop has 4K screen with a scaling factor of 200%. The main window appeared with a tiny font without any scaling.

The issue with the window positions not getting restored correctly is still there.

@jezek

jezek commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

@mhirki i'm sorry, i don't have a way to test/debug on windows... i don't have a windows machine at home, nor a 4K display... i've tested the windows client only under wine on linux

quick look on net says the wrongly positioned windows can be something with DPI... i've read, that sdl3 supports scaling, so i'll try to consult and make an attempt to fix the positions and scaling (also resolve the new conflicts and rebase)... could you provide more info (and/or screenshot) on what is wrong with the windows positions and where the windows should be expected?.. thx

- Increased vesion to 4.9.3.0.2.0.
- Add USE_SDL3 macros thorough the code.
- Add OS_SUB_SDL3 and OS_SUB_GCU_SDL3 and use it in VERSION_OS_SUB.
- Add Unified makefile.sdl3 for linux compiling and windows cross compiling.
  - Compile windows sdl3 client without wine and tolua.exe.
  - Remove unnecessary generation rules for common/z_pack.
  - Refactor the tolua file generation.
  - Make tomenet and tomenet.exe executables in one run in SDL3 client.
  - Add automatic header-dependency tracking with -MMD/-MP.
- Update .gitignore.
- Introducing SDL3_GAME_PATH, SDL3_USER_PATH and SDL3_PATH_SEP variables.
- Introduce SDL3 user directory.
  - Declare and expose new ANGBAND_USER_DIR* pointers based on ANGBAND_DIR*.
  - Inform about creating user directories, refactor.
  - Copy default scripts into `ANGBAND_USER_DIR_SCPT` when it's created.
  - Redirect SDL3 client file I/O to the SDL3 user directory.
  - Store temporary files and logs in the SDL3 temp folder.
  - Rename copy_file to my_fcopy.
  - Edit my_fopen to open files with fallback and use instead of fopen in SDL3 client.
  - Prefer user dir for fonts/tilesets/macros; install audio packs to user xtra.
  - Use user dir when saving sound/music.cfg files.
  - Override the user storage dir via TOMENET_SDL3_USER_PATH environment variable.
  - Using a dir in sdl3 user path as tmpdir when no env value is set.
- Add common/net-sdl3.c using the SDL3 SDL_net library and use it with sdl3 clients.
- Add main-sdl3.c based on main-x11.c and use it in SDL3 client.
  - Add multi-layer multi-masks tiles support.
  - Add tile cache support, but turn it off (not needed, it is fast).
  - Hide disable_tile_cache into TILE_CACHE_SIZE ifdef macro.
  - Set terminal index during initialization.
  - Defer graphics until windows are initialized.
  - Graphic tiles are initialized after pref file is loaded.
  - Print warnings when pref file is not loaded into msg window when possible.
  - Graphics pref file now contains information about masks colors.
  - Per-subtileset mask colors are now loaded from .prf files and used.
  - Support PCF and TTF fonts in the SDL3 fonts menu, handle PCF fonts as graphical.
  - Add pcf fonts to lib/xtra/font for sdl3 clients.
  - Add window decorations toggle to settings file and in-game window flags menu.
  - On window move, store coordinates considering decorations.
  - Windows are created with decorations by default.
  - Draw only borders with SDL3_DEFAULT_BORDER_WIDTH width.
  - Using semi-transparent black as top tile outline color for UG_2MASK mode.
  - Graphics tiles outline layer generation for fg/bg tiles when UG_2MASK
    mode. Option to force outline generation of specific width.
  - Graphics tiles preferences on-the-fly change and
    tiles with layers preview in in-game graphics menu.
  - Graphic subtiles implemenation. Respects subtiles in preview an cache.
  - Graphics cache resets subset/index during init and teardown to keep entries clean before reuse.
  - Loading graphics images of tiles and subtiles from user location first.
  - Add tileset resize modes support, default is NEAREST.
  - For keyboard handling use only key press events (no text input).
  - Startup logo is graphic only when all used solid tiles are loaded.
  - Reset raw graphics definitions before pref load
  - Store raw graphics in their source tileset
  - Cache scaled tilesets to disk and reuse them when needed
  - Hide all disable_tileset_caching into USE_GRAPHICS macro guard
  - Fix casino display functions to consider use_graphics and rawpict_hook.
- Using tomenet.cfg in sdl3 user path as config (based on .tomenetrc).
- Make check_guide_checksums work for sdl3 with curl & ssl.
- Removing goto from client/client.c in mangrc read function.
- Use SDL3_image library for screenshots, but it is optional.
  - If not using SDL3_image, save screenshots to BMP instead of PNG.
- Add SDL3_STICKY_KEYS macro and disable by default.
- Create snd-sdl3.c file based on snd-sdl.c.
  - Switch SDL2 client sound to SDL3.
  - Allow sound code to compile with either `SOUND_SDL` or `SOUND_SDL3`.
  - Fix sdl3 quit on music quit, add debug logs to sdl3 unarchive.
  - Guard SDL mixer shutdown.
  - Don't use file descriptors (FD) and music caching.
  - Cache only currently played track without decoding.
  - Fix wrong mutex unlock when loading music (also in snd-sdl.c).
  - Refactor sound_sdl_init function.
  - Fix audio init failure cleanup.
  - Add subset logic.
  - Fix jukebox autoplay finish and destuctive pack-switch.
  - Fix post-autoplay cursor restore.
  - Fix autoplay stop after first song after a/u/e session.
  - Stabilize jukebox restore/fadeout/shutdown state across mixer reloads and previews.
  - Preserve force-disabled and runtime-disabled SDL3 audio state correctly in config and toggles.
  - Ignore transient EMFILE/ENFILE when loading audio events.
- Add libarchive-based unzipping sound/music pack 7zipped files.
  - Detect libarchive in makefile.sdl3 via pkg-config and link when available.
  - Notify when unpacking unsupprted 7z encrypted archive.
  - More archives support in sdl3 clients (.zip, .tar, .tar.gz).
- Use SDL_OpenURL for file and link opening.
- Fix double separator in lua scripts.
- Treating the SDL3 Delete key separately from Backspace so prompts.
- In knowledge menu, open last screenshot instead of conversion.
  - Open user folders in in-game knowledge menu too.
- Make macroset scan OS independent for SDL3 test clients.
- Create fake but deterministic MAC depending on PC stats.
- Add basic player sounds according to sound.cfg.default content.
- Add .prf files to lib/user for sdl3 clients.
- Get rid of most compiler warnings.
- Build sdl3 linux client to prefer .so beside the binary.
- Make SDL3 ip_iface return IPv4 string like Windows client (Can't make
  work like windows client, returns  different string).
- Add optional GCU support for SDL3 Linux client build, default is off.
- Added build scripts for fedora 41 & 43 distrobox build containers.
- Added CI for github with Fedora 41 build image and compile-check workflow.
- Added CI for building client/server release archives on tag push and
  append them if release is made.
- Updated guide with info about sdl3 clients how to build them.
- Add mask color documentation for sdl3 clients tileset bitmap.
- Default to x11 video driver in sdl3 linux client
- Fix: stop -X from enabling log redirection.
- Quit cleanly on window close.
- Save live window layout before config
@jezek

jezek commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

hellou @mhirki

i think i found the windows position bug... could you try again?

the decorations being off screen is intentional now... the coordinates in config are referring to client (canvas), not its frame... on linux the off screen rendering is not problem, cause the WM snaps the off screen decoration into visible area and moves the window to see the decorations... it seems windows is not so aggressive... maybe the config coordinates should refer to frame instead of client...

about scaling... i've read some docs, consulted some AI... and seems not so straight forward... apart from display scale there is pixel density and the windows can move from one monitor with different scaling to another and i'm not confident about the implementation... i have some draft produced by AI (a minimal one without re-scaling at scale change), but there are many changes and i have to understand them (i don't want to ship something i don't understand) and make some tweaks...

in meantime could you try a bigger font? that should do the trick... if the biggest pcf font is not enough, maybe some ttf font... i've tested on and got good results with Hack-Regular.ttf* fixed-width font (maybe we should consider include some ttf fonts by default)... maybe easiest would be on first run detect the scaling and just choose bigger default fonts if scaled... (of course in future there can be a better solution with dynamic scaling change, etc... but for now, for the sake of this PR, i think, we should aim for simplicity)

*) for .ttf fonts in config use it like Name.ttf <size> (e.g. Term-2_Font Hack-Regular.ttf 12), or choose from ingame font menu (= f) and after selecting a ttf font use +/- to make it bigger/smaller

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants