From d23c1a853555b2e23712fc6767e8a3f61ccd0360 Mon Sep 17 00:00:00 2001 From: Felipe Braz Date: Fri, 26 Jun 2026 19:49:23 -0300 Subject: [PATCH 1/3] build(linux): update base image to Ubuntu 26.04 LTS and fix include casing Updates the Docker base image and related documentation to use Ubuntu 26.04 instead of 24.04. Resolves a case-sensitivity build error in MiniAudioManager.cpp caused by conflicting `File.h` and `file.h` includes that surfaced with the new compiler/environment. --- .../Source/MiniAudioDevice/MiniAudioManager.cpp | 2 +- docs/HOWTO/INSTALLATION.md | 4 ++-- docs/WORKDIR/phases/PHASE04_POLISH_HARDENING.md | 8 ++++---- resources/dockerbuild/Dockerfile.linux | 2 +- scripts/README.md | 2 +- scripts/README_DOCKER_SCRIPTS.md | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp index ad50a45d2cc..01ce398e6ab 100644 --- a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp @@ -60,7 +60,7 @@ #include "GameLogic/GameLogic.h" #include "GameLogic/TerrainLogic.h" -#include "Common/File.h" +#include "Common/file.h" #include "VideoDevice/FFmpeg/FFmpegFile.h" extern "C" { diff --git a/docs/HOWTO/INSTALLATION.md b/docs/HOWTO/INSTALLATION.md index 8e511a49072..346e8f8e370 100644 --- a/docs/HOWTO/INSTALLATION.md +++ b/docs/HOWTO/INSTALLATION.md @@ -70,7 +70,7 @@ GeneralsX has been developed and tested primarily on the following environments: -- Ubuntu 24.04 LTS (x86_64) +- Ubuntu 26.04 LTS (x86_64) - macOS 26 "Tahoe" on Apple Silicon (M1 / ARM64) Other Linux distributions or macOS versions may work, but you may need to install additional dependencies manually. On some systems, certain libraries might need to be built from source. @@ -81,7 +81,7 @@ Current development and test matrix: | Platform | Architecture | Status | |--------------------|------------------------|---------| -| Ubuntu 24.04 LTS | x86_64 | Working | +| Ubuntu 26.04 LTS | x86_64 | Working | | macOS 26 "Tahoe" | ARM64 (Apple Silicon) | Working | Support for other platforms and configurations is possible but not yet officially tested. diff --git a/docs/WORKDIR/phases/PHASE04_POLISH_HARDENING.md b/docs/WORKDIR/phases/PHASE04_POLISH_HARDENING.md index 5ae1f247c7e..a8c3d387207 100644 --- a/docs/WORKDIR/phases/PHASE04_POLISH_HARDENING.md +++ b/docs/WORKDIR/phases/PHASE04_POLISH_HARDENING.md @@ -85,7 +85,7 @@ Stabilize, optimize, and prepare for community release. - Invalid command-line arguments - [ ] **Compatibility tests** (multiple environments): - - Ubuntu 22.04, 24.04 (LTS targets) + - Ubuntu 22.04, 26.04 (LTS targets) - Fedora 40+ (latest kernel/drivers) - Arch Linux (rolling release, bleeding edge) - Steam Deck (Proton comparison: native vs. Wine) @@ -231,7 +231,7 @@ Stabilize, optimize, and prepare for community release. **Target Distros**: - [ ] Ubuntu 22.04 LTS (stable, large user base) -- [ ] Ubuntu 24.04 LTS (latest LTS) +- [ ] Ubuntu 26.04 LTS (latest LTS) - [ ] Fedora 40+ (cutting edge, latest Mesa) - [ ] Arch Linux (rolling release, community favorite) - [ ] Debian 12 (stable, server-oriented but some gamers) @@ -241,7 +241,7 @@ Stabilize, optimize, and prepare for community release. | Distro | Vulkan Driver | GPU | Status | Notes | |--------|---------------|-----|--------|-------| | Ubuntu 22.04 | Mesa RADV | AMD RX 6800 | ❓ | Test here | -| Ubuntu 24.04 | Mesa RADV | AMD RX 6800 | ❓ | Test here | +| Ubuntu 26.04 | Mesa RADV | AMD RX 6800 | ❓ | Test here | | Fedora 40 | Mesa RADV | AMD RX 7900 | ❓ | Test here | | Arch | Mesa RADV | AMD RX 580 | ❓ | Test here | | Ubuntu 22.04 | NVIDIA 550 | RTX 3080 | ❓ | Test here | @@ -381,7 +381,7 @@ Phase 4 is **COMPLETE** when: - [ ] No memory leaks (Valgrind clean) - [ ] Case-insensitive filesystem working (no "file not found" errors) - [ ] Passes 2-hour stress test (no crashes, minimal performance drop) -- [ ] Works on Ubuntu 22.04, 24.04, Fedora 40, Arch (verified) +- [ ] Works on Ubuntu 22.04, 26.04, Fedora 40, Arch (verified) - [ ] AppImage or Flatpak release available - [ ] Documentation complete (`INSTALL_LINUX.md`, `TROUBLESHOOTING_LINUX.md`) - [ ] Community beta tested (>10 testers, feedback incorporated) diff --git a/resources/dockerbuild/Dockerfile.linux b/resources/dockerbuild/Dockerfile.linux index 8e226899710..960a5c4388b 100644 --- a/resources/dockerbuild/Dockerfile.linux +++ b/resources/dockerbuild/Dockerfile.linux @@ -2,7 +2,7 @@ # Base image for building GeneralsX/GeneralsXZH Linux binaries # Platform: linux/amd64 (x86_64) -FROM ubuntu:24.04 +FROM ubuntu:26.04 LABEL maintainer="GeneralsX Project" LABEL description="Linux native build environment for GeneralsX (GCC/Clang + CMake + vcpkg)" diff --git a/scripts/README.md b/scripts/README.md index 0263d06c0f0..7b146acea17 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -173,7 +173,7 @@ Scripts support customization: ```bash # Custom Docker image base -export DOCKER_IMAGE="ubuntu:24.04" +export DOCKER_IMAGE="ubuntu:26.04" ./scripts/build/linux/docker-build-linux-zh.sh # Flatpak PoC: inject newer libxcb/X11 libs from an external directory diff --git a/scripts/README_DOCKER_SCRIPTS.md b/scripts/README_DOCKER_SCRIPTS.md index 5ed2f172b80..ae91dfc8318 100644 --- a/scripts/README_DOCKER_SCRIPTS.md +++ b/scripts/README_DOCKER_SCRIPTS.md @@ -183,7 +183,7 @@ Scripts support environment variables: ```bash # Custom Docker image -export DOCKER_IMAGE="ubuntu:24.04" +export DOCKER_IMAGE="ubuntu:26.04" ./scripts/docker-build-linux-zh.sh # Custom log directory From 3a599a10d7bf9c0bc53bf1463aa13e012b20a17c Mon Sep 17 00:00:00 2001 From: Felipe Braz Date: Fri, 26 Jun 2026 19:53:46 -0300 Subject: [PATCH 2/3] fix(scripts): disable DXVK FPS overlay by default Disables the DXVK FPS overlay (`DXVK_HUD=0`) in all Linux execution and deployment scripts. The game already has a native FPS counter, so the Vulkan overlay is redundant and clutters the screen. Fixes an issue where casual players would see the overlay enabled by default. --- scripts/build/linux/bundle-linux-zh.sh | 5 ++--- scripts/build/linux/bundle-linux.sh | 5 ++--- scripts/build/linux/deploy-linux-zh.sh | 11 +++-------- scripts/build/linux/run-linux-zh.sh | 2 +- scripts/build/linux/run-linux.sh | 2 +- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/scripts/build/linux/bundle-linux-zh.sh b/scripts/build/linux/bundle-linux-zh.sh index d52f6749661..828095bda73 100755 --- a/scripts/build/linux/bundle-linux-zh.sh +++ b/scripts/build/linux/bundle-linux-zh.sh @@ -175,10 +175,9 @@ if [[ -f "${SCRIPT_DIR}/libsage_patch.so" && "${SAGE_PATCH_DISABLED:-0}" != "1" else export LD_PRELOAD="${SCRIPT_DIR}/libsage_patch.so" fi - export DXVK_HUD="${DXVK_HUD:-fps}" -else - export DXVK_HUD="${DXVK_HUD:-0}" fi +# DXVK HUD is disabled by default because Generals has a native FPS counter. +export DXVK_HUD="${DXVK_HUD:-0}" # Auto-detect base Generals install path if [[ -z "${CNC_GENERALS_INSTALLPATH:-}" && -d "${SCRIPT_DIR}/../Generals" ]]; then diff --git a/scripts/build/linux/bundle-linux.sh b/scripts/build/linux/bundle-linux.sh index 09d6100a1e6..aee1a5761d1 100755 --- a/scripts/build/linux/bundle-linux.sh +++ b/scripts/build/linux/bundle-linux.sh @@ -174,10 +174,9 @@ if [[ -f "${SCRIPT_DIR}/libsage_patch.so" && "${SAGE_PATCH_DISABLED:-0}" != "1" else export LD_PRELOAD="${SCRIPT_DIR}/libsage_patch.so" fi - export DXVK_HUD="${DXVK_HUD:-fps}" -else - export DXVK_HUD="${DXVK_HUD:-0}" fi +# DXVK HUD is disabled by default because Generals has a native FPS counter. +export DXVK_HUD="${DXVK_HUD:-0}" # Auto-detect base Generals install path if [[ -z "${CNC_GENERALS_INSTALLPATH:-}" && -d "${SCRIPT_DIR}/../Generals" ]]; then diff --git a/scripts/build/linux/deploy-linux-zh.sh b/scripts/build/linux/deploy-linux-zh.sh index 5659d66ae9c..6addec904cb 100755 --- a/scripts/build/linux/deploy-linux-zh.sh +++ b/scripts/build/linux/deploy-linux-zh.sh @@ -190,14 +190,9 @@ export LD_LIBRARY_PATH="${SCRIPT_DIR}:${LD_LIBRARY_PATH:-}" # Set DXVK environment export DXVK_WSI_DRIVER="SDL3" export DXVK_LOG_LEVEL="${DXVK_LOG_LEVEL:-info}" -# DXVK HUD: SagePatch builds default to "fps" so casual users see frame rate -# without extra config. Set DXVK_HUD=0 explicitly to disable, or anything else -# (e.g. fps,memory,version) to customize. See DXVK docs for full list. -if [[ -f "${SCRIPT_DIR}/libsage_patch.so" && "${SAGE_PATCH_DISABLED:-0}" != "1" ]]; then - export DXVK_HUD="${DXVK_HUD:-fps}" -else - export DXVK_HUD="${DXVK_HUD:-0}" -fi +# DXVK HUD is disabled by default because Generals has a native FPS counter. +# Set DXVK_HUD=fps,memory,version or similar to customize. See DXVK docs for full list. +export DXVK_HUD="${DXVK_HUD:-0}" # SagePatch (optional QoL features). Loaded via LD_PRELOAD so it can interpose # SDL3 functions for hot-keys (F11 screenshot, Scroll Lock cursor lock, diff --git a/scripts/build/linux/run-linux-zh.sh b/scripts/build/linux/run-linux-zh.sh index fcfd556e2b0..cccef1c9622 100755 --- a/scripts/build/linux/run-linux-zh.sh +++ b/scripts/build/linux/run-linux-zh.sh @@ -45,7 +45,7 @@ export LD_LIBRARY_PATH="${GAME_DIR}:${LD_LIBRARY_PATH:-}" # Set DXVK environment export DXVK_WSI_DRIVER="SDL3" export DXVK_LOG_LEVEL="${DXVK_LOG_LEVEL:-info}" # Override with 'debug' if needed -export DXVK_HUD="${DXVK_HUD:-devinfo,fps}" # Show GPU info + FPS overlay; override with DXVK_HUD=0 to disable +export DXVK_HUD="${DXVK_HUD:-0}" # Disabled by default; Generals has native FPS counter # GeneralsX @bugfix BenderAI 06/03/2026 - Exclude LLVMpipe Vulkan ICD (LLVM 20.x crash workaround) # libvulkan_lvp.so (LLVMpipe) crashes during static initialization with LLVM 20.x. diff --git a/scripts/build/linux/run-linux.sh b/scripts/build/linux/run-linux.sh index 8c11ed2a01e..3d4b64d9334 100755 --- a/scripts/build/linux/run-linux.sh +++ b/scripts/build/linux/run-linux.sh @@ -29,7 +29,7 @@ export LD_LIBRARY_PATH="${GAME_DIR}:${LD_LIBRARY_PATH:-}" # Set DXVK environment export DXVK_WSI_DRIVER="SDL3" export DXVK_LOG_LEVEL="${DXVK_LOG_LEVEL:-info}" # Override with 'debug' if needed -export DXVK_HUD="${DXVK_HUD:-devinfo,fps}" # Show GPU info + FPS overlay; override with DXVK_HUD=0 to disable +export DXVK_HUD="${DXVK_HUD:-0}" # Disabled by default; Generals has native FPS counter # GeneralsX @bugfix BenderAI 06/03/2026 - Exclude LLVMpipe Vulkan ICD (LLVM 20.x crash workaround) # libvulkan_lvp.so (LLVMpipe) crashes during static initialization with LLVM 20.x. From 520d21ea7791d3bb8601e714b6b6143d4e9daf50 Mon Sep 17 00:00:00 2001 From: Felipe Braz Date: Fri, 26 Jun 2026 20:09:51 -0300 Subject: [PATCH 3/3] fix(graphics): support A4R4G4B4/R5G6B5 downsampling on Linux Backports the manual box filter downsampling for A4R4G4B4 and R5G6B5 textures from macOS to Linux. This fixes an issue where infantry shadows and recolored textures rendered entirely black at lower mipmap levels because the GLI library does not support these formats. Closes issue where infantry was rendering black on Linux. --- .../Code/CompatLib/Source/d3dx8_compat.cpp | 75 +++++++++++++++++++ docs/DEV_BLOG/2026-06-DIARY.md | 3 + 2 files changed, 78 insertions(+) diff --git a/GeneralsMD/Code/CompatLib/Source/d3dx8_compat.cpp b/GeneralsMD/Code/CompatLib/Source/d3dx8_compat.cpp index 53db8027ad6..60dbb60e89d 100644 --- a/GeneralsMD/Code/CompatLib/Source/d3dx8_compat.cpp +++ b/GeneralsMD/Code/CompatLib/Source/d3dx8_compat.cpp @@ -107,6 +107,81 @@ D3DXLoadSurfaceFromSurface( } #ifndef __APPLE__ + // GeneralsX @bugfix Antigravity 26/06/2026 Linux: GLI lacks support for A4R4G4B4/R5G6B5 formats. + // We use manual box filter downsampling for these formats to fix black infantry rendering. + if (descDest.Width == descSrc.Width / 2 && descDest.Height == descSrc.Height / 2) + { + if (descSrc.Format == D3DFMT_A4R4G4B4) + { + // Box filter for A4R4G4B4: average 2x2 blocks + const uint16_t *src = (const uint16_t *)srcRect.pBits; + uint16_t *dst = (uint16_t *)destRect.pBits; + uint32_t srcPitch16 = srcRect.Pitch / 2; + uint32_t dstPitch16 = destRect.Pitch / 2; + + for (uint32_t y = 0; y < descDest.Height; y++) + { + for (uint32_t x = 0; x < descDest.Width; x++) + { + uint32_t sx = x * 2; + uint32_t sy = y * 2; + uint16_t p00 = src[sy * srcPitch16 + sx]; + uint16_t p10 = src[sy * srcPitch16 + sx + 1]; + uint16_t p01 = src[(sy + 1) * srcPitch16 + sx]; + uint16_t p11 = src[(sy + 1) * srcPitch16 + sx + 1]; + + // Extract and average each channel (A4 R4 G4 B4) + uint32_t a = (((p00 >> 12) & 0x0F) + ((p10 >> 12) & 0x0F) + + ((p01 >> 12) & 0x0F) + ((p11 >> 12) & 0x0F) + 2) >> 2; + uint32_t r = (((p00 >> 8) & 0x0F) + ((p10 >> 8) & 0x0F) + + ((p01 >> 8) & 0x0F) + ((p11 >> 8) & 0x0F) + 2) >> 2; + uint32_t g = (((p00 >> 4) & 0x0F) + ((p10 >> 4) & 0x0F) + + ((p01 >> 4) & 0x0F) + ((p11 >> 4) & 0x0F) + 2) >> 2; + uint32_t b = ((p00 & 0x0F) + (p10 & 0x0F) + + (p01 & 0x0F) + (p11 & 0x0F) + 2) >> 2; + + dst[y * dstPitch16 + x] = (uint16_t)((a << 12) | (r << 8) | (g << 4) | b); + } + } + pDestSurface->UnlockRect(); + pSrcSurface->UnlockRect(); + return D3D_OK; + } + else if (descSrc.Format == D3DFMT_R5G6B5) + { + // Box filter for R5G6B5: average 2x2 blocks + const uint16_t *src = (const uint16_t *)srcRect.pBits; + uint16_t *dst = (uint16_t *)destRect.pBits; + uint32_t srcPitch16 = srcRect.Pitch / 2; + uint32_t dstPitch16 = destRect.Pitch / 2; + + for (uint32_t y = 0; y < descDest.Height; y++) + { + for (uint32_t x = 0; x < descDest.Width; x++) + { + uint32_t sx = x * 2; + uint32_t sy = y * 2; + uint16_t p00 = src[sy * srcPitch16 + sx]; + uint16_t p10 = src[sy * srcPitch16 + sx + 1]; + uint16_t p01 = src[(sy + 1) * srcPitch16 + sx]; + uint16_t p11 = src[(sy + 1) * srcPitch16 + sx + 1]; + + // Extract and average each channel (R5 G6 B5) + uint32_t r = (((p00 >> 11) & 0x1F) + ((p11 >> 11) & 0x1F) + + ((p01 >> 11) & 0x1F) + ((p10 >> 11) & 0x1F) + 2) >> 2; + uint32_t g = (((p00 >> 5) & 0x3F) + ((p11 >> 5) & 0x3F) + + ((p01 >> 5) & 0x3F) + ((p10 >> 5) & 0x3F) + 2) >> 2; + uint32_t b = ((p00 & 0x1F) + (p11 & 0x1F) + + (p01 & 0x1F) + (p10 & 0x1F) + 2) >> 2; + + dst[y * dstPitch16 + x] = (uint16_t)((r << 11) | (g << 5) | b); + } + } + pDestSurface->UnlockRect(); + pSrcSurface->UnlockRect(); + return D3D_OK; + } + } // Pick a compatible format gli::format imageFormat = gli::format::FORMAT_RGBA8_UNORM_PACK8; diff --git a/docs/DEV_BLOG/2026-06-DIARY.md b/docs/DEV_BLOG/2026-06-DIARY.md index 62d3a1112dc..98455bb3fed 100644 --- a/docs/DEV_BLOG/2026-06-DIARY.md +++ b/docs/DEV_BLOG/2026-06-DIARY.md @@ -1,5 +1,8 @@ # Development Diary - June 2026 +## 2026-06-26: Support D3DFMT_A4R4G4B4 and D3DFMT_R5G6B5 Downsampling on Linux + +- **DirectX 8 Downsampling Parity on Linux**: Backported the manual box filter downsampling logic for `D3DFMT_A4R4G4B4` and `D3DFMT_R5G6B5` from macOS to Linux in [d3dx8_compat.cpp](file:///home/felipe/Projects/GeneralsX/GeneralsMD/Code/CompatLib/Source/d3dx8_compat.cpp). Previously, the Linux port relied on the GLI library to generate mipmaps, which lacked support for these specific formats, causing `D3DXLoadSurfaceFromSurface` to fail. This failure resulted in team/house recolored textures on infantry rendering as solid black silhouettes at lower mipmap levels. Bypassing GLI for these formats and applying the manual box filter restores rendering parity with macOS and original Windows targets. ## 2026-06-21: Use Git Clone with Fallback for Assets in Replay Tests - **GitLab & GitHub Resilient Assets Fetch**: Replaced `actions/checkout` with a direct `git clone` and `git lfs pull` sequence in [replay-tests.yml](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/.github/workflows/replay-tests.yml) to retrieve large game asset archives. Implemented try/catch logic in the shell script: it attempts to clone the assets from GitLab first (benefiting from GitLab's larger LFS transfer limits), and falls back to GitHub if the GitLab clone or LFS pull fails. This maintains maximum build reliability while bypassing GitHub's LFS restrictions where possible.