From 05d64ea2990af24417e6e89da46d2f95d8c3d171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=BCndig?= Date: Sat, 15 Aug 2026 14:21:17 +0200 Subject: [PATCH 1/5] linux: enable the HTML5 builder in Solar2DBuilder The packager is already compiled in; only CORONABUILDER_HTML5 was missing, so the binary answered that HTML5 builds are not supported on this operating system. --- platform/linux/CMakeList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/linux/CMakeList.txt b/platform/linux/CMakeList.txt index ee1677998..a4043d7c3 100644 --- a/platform/linux/CMakeList.txt +++ b/platform/linux/CMakeList.txt @@ -1028,7 +1028,7 @@ target_compile_definitions( Solar2DSimulator PUBLIC target_compile_definitions( Solar2DBuilder PUBLIC Rtt_BUILD_REVISION=${BUILD_NUMBER} Rtt_BUILD_YEAR=${YEAR} - LUA_USE_POPEN Rtt_LUA_COMPILER Rtt_SIMULATOR CORONABUILDER_LINUX LUA_DL_DLOPEN + LUA_USE_POPEN Rtt_LUA_COMPILER Rtt_SIMULATOR CORONABUILDER_LINUX CORONABUILDER_HTML5 LUA_DL_DLOPEN Rtt_LINUX_ENV ALMIXER_COMPILE_WITHOUT_SDL SOUND_SUPPORTS_WAV SOUND_SUPPORTS_MPG123 SOUND_SUPPORTS_OGG OPT_GENERIC HAVE_STRERROR NO_REAL ENABLE_ALMIXER_THREADS LINUX_LIB) From 70b144d6f7c5149898db8d203c40742ef90c8461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=BCndig?= Date: Sat, 15 Aug 2026 14:21:17 +0200 Subject: [PATCH 2/5] linux: enable Android builds in Solar2DBuilder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Defines CORONABUILDER_ANDROID, adds the Rtt_AndroidSupportTools.c the factory calls from inside that gate, gives the AndroidValidation path and GetResourceDirectory() a Linux arm — the latter ran off the end of a function returning const char*, killing the build in free() with no diagnostic. --- platform/linux/CMakeList.txt | 3 ++- .../Rtt_AppPackagerAndroidFactory.cpp | 2 ++ tools/CoronaBuilder/Rtt_AppPackagerFactory.cpp | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/platform/linux/CMakeList.txt b/platform/linux/CMakeList.txt index a4043d7c3..d16e7995d 100644 --- a/platform/linux/CMakeList.txt +++ b/platform/linux/CMakeList.txt @@ -959,6 +959,7 @@ add_executable( Solar2DBuilder ${CORONA_ROOT}/tools/CoronaBuilder/main.cpp ${CORONA_ROOT}/tools/CoronaBuilder/Rtt_CoronaBuilder.cpp ${CORONA_ROOT}/tools/CoronaBuilder/Rtt_AppPackagerFactory.cpp + ${CORONA_ROOT}/platform/shared/Rtt_AndroidSupportTools.c ${CORONA_ROOT}/tools/CoronaBuilder/Rtt_AppPackagerAndroidFactory.cpp ${CORONA_ROOT}/tools/CoronaBuilder/Rtt_AppPackagerHTML5Factory.cpp ${CORONA_ROOT}/tools/CoronaBuilder/Rtt_AppPackagerLinuxFactory.cpp @@ -1028,7 +1029,7 @@ target_compile_definitions( Solar2DSimulator PUBLIC target_compile_definitions( Solar2DBuilder PUBLIC Rtt_BUILD_REVISION=${BUILD_NUMBER} Rtt_BUILD_YEAR=${YEAR} - LUA_USE_POPEN Rtt_LUA_COMPILER Rtt_SIMULATOR CORONABUILDER_LINUX CORONABUILDER_HTML5 LUA_DL_DLOPEN + LUA_USE_POPEN Rtt_LUA_COMPILER Rtt_SIMULATOR CORONABUILDER_LINUX CORONABUILDER_HTML5 CORONABUILDER_ANDROID LUA_DL_DLOPEN Rtt_LINUX_ENV ALMIXER_COMPILE_WITHOUT_SDL SOUND_SUPPORTS_WAV SOUND_SUPPORTS_MPG123 SOUND_SUPPORTS_OGG OPT_GENERIC HAVE_STRERROR NO_REAL ENABLE_ALMIXER_THREADS LINUX_LIB) diff --git a/tools/CoronaBuilder/Rtt_AppPackagerAndroidFactory.cpp b/tools/CoronaBuilder/Rtt_AppPackagerAndroidFactory.cpp index 33bf5e06b..af077cc8c 100644 --- a/tools/CoronaBuilder/Rtt_AppPackagerAndroidFactory.cpp +++ b/tools/CoronaBuilder/Rtt_AppPackagerAndroidFactory.cpp @@ -138,6 +138,8 @@ AppPackagerFactory::CreatePackagerParamsAndroid( scriptPathStr.Set(GetResourceDirectory()); #if defined(Rtt_MAC_ENV) scriptPathStr.Append("/AndroidValidation.lu"); +#elif defined(Rtt_LINUX_ENV) + scriptPathStr.Append("/AndroidValidation.lua"); #elif defined(Rtt_WIN_ENV) scriptPathStr.Append("/AndroidValidation.lua"); #endif diff --git a/tools/CoronaBuilder/Rtt_AppPackagerFactory.cpp b/tools/CoronaBuilder/Rtt_AppPackagerFactory.cpp index 2c2c61317..ca7fdf737 100644 --- a/tools/CoronaBuilder/Rtt_AppPackagerFactory.cpp +++ b/tools/CoronaBuilder/Rtt_AppPackagerFactory.cpp @@ -32,6 +32,10 @@ #if defined(CORONABUILDER_LINUX) #include "Rtt_LinuxAppPackager.h" #endif +#if defined(Rtt_LINUX_ENV) +#include "Rtt_LinuxUtils.h" +#include +#endif #ifdef Rtt_WIN_ENV #include "Rtt_JavaHost.h" @@ -394,6 +398,16 @@ AppPackagerFactory::GetResourceDirectory() const return GetResourceDirectoryOSX(); #elif defined(Rtt_WIN_ENV) return GetResourceDirectoryWin(); +#elif defined(Rtt_LINUX_ENV) + // Resources live beside the executable in the Linux layout. + static std::string resourceDir; + if (resourceDir.empty()) + { + resourceDir = std::string(GetStartupPath(NULL)) + "/Resources"; + } + return resourceDir.c_str(); +#else + return NULL; #endif } From 63ba217e6ad9e23b9bb0cc86b4ceb78f91a6870b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=BCndig?= Date: Sat, 15 Aug 2026 14:21:27 +0200 Subject: [PATCH 3/5] linux: install AndroidValidation.lua next to the builder The Android packager reads it from disk rather than through LUA_SOURCES, so without it every build stops at "Could not find script file". --- platform/linux/CMakeResources.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/linux/CMakeResources.txt b/platform/linux/CMakeResources.txt index 0909be542..9d7fa718a 100644 --- a/platform/linux/CMakeResources.txt +++ b/platform/linux/CMakeResources.txt @@ -21,6 +21,7 @@ file(COPY "${CORONA_ROOT}/platform/resources/json.lua" DESTINATION ${RESOURCES} file(COPY "${CORONA_ROOT}/platform/resources/dkjson.lua" DESTINATION ${RESOURCES} FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) file(COPY "${CORONA_ROOT}/platform/resources/CoronaPListSupport.lua" DESTINATION ${RESOURCES} FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) file(COPY "${CORONA_ROOT}/platform/resources/AppSettings.lua" DESTINATION ${RESOURCES} FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +file(COPY "${CORONA_ROOT}/platform/resources/AndroidValidation.lua" DESTINATION ${RESOURCES} FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) file(COPY "${CORONA_ROOT}/platform/android/create_build_properties.lua" DESTINATION ${RESOURCES} FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) file(COPY "${CORONA_ROOT}/platform/android/resources/build.xml" DESTINATION ${RESOURCES} FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) From 748969abd7e0992e3bef6979a9e5b3db7dd8f8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=BCndig?= Date: Sat, 15 Aug 2026 14:21:27 +0200 Subject: [PATCH 4/5] linux: keep the builder's sandbox out of the filesystem root The paths start empty, so appending left the builder writing to /Documents and its three siblings, which only root can create; they now go under TMPDIR, one directory per uid (first reported in #891). --- tools/CoronaBuilder/main.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/CoronaBuilder/main.cpp b/tools/CoronaBuilder/main.cpp index cd6474979..ca3496444 100644 --- a/tools/CoronaBuilder/main.cpp +++ b/tools/CoronaBuilder/main.cpp @@ -13,6 +13,8 @@ #include "Rtt_LinuxSimulatorView.h" #include "Rtt_LinuxUtils.h" #include +#include +#include using namespace std; @@ -28,10 +30,19 @@ int main(int argc, const char *argv[]) string skinDir; // setup directory paths - documentsDir.append("/Documents"); - temporaryDir.append("/TemporaryFiles"); - cachesDir.append("/CachedFiles"); - systemCachesDir.append("/.system"); + // The strings start empty, so appending alone puts the builder's sandbox at + // the root of the filesystem, writable only by root. Keep it in TMPDIR, one + // per uid so a shared /tmp does not lock the second user out. + const char *tmpDir = getenv("TMPDIR"); + if (tmpDir == NULL || tmpDir[0] == '\0') + { + tmpDir = "/tmp"; + } + string sandboxDir = string(tmpDir) + "/Solar2DBuilder-" + to_string(getuid()); + documentsDir = sandboxDir + "/Documents"; + temporaryDir = sandboxDir + "/TemporaryFiles"; + cachesDir = sandboxDir + "/CachedFiles"; + systemCachesDir = sandboxDir + "/.system"; Rtt::LinuxConsolePlatform *platform = new Rtt::LinuxConsolePlatform(pathToApp.c_str(), documentsDir.c_str(), temporaryDir.c_str(), cachesDir.c_str(), systemCachesDir.c_str(), skinDir.c_str(), GetStartupPath(NULL)); Rtt::LinuxPlatformServices services(platform); From 39e3789586bb04dd19106e7b6ca39603a004b3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=BCndig?= Date: Sat, 15 Aug 2026 14:21:28 +0200 Subject: [PATCH 5/5] linux: fix scrambled channels in display.save() A capture is tagged kBGRA but the packed readback lands in memory as A,R,G,B, so the byte-order writers swapped red and green and took blue from the alpha byte; the Linux writer now reports kARGB, which savePNG and saveJPG grow a case for. --- platform/linux/src/Rtt_LinuxBitmap.cpp | 11 ++++++++ platform/shared/Rtt_BitmapUtils.cpp | 37 +++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/platform/linux/src/Rtt_LinuxBitmap.cpp b/platform/linux/src/Rtt_LinuxBitmap.cpp index 0a2aa7807..acc286995 100644 --- a/platform/linux/src/Rtt_LinuxBitmap.cpp +++ b/platform/linux/src/Rtt_LinuxBitmap.cpp @@ -196,6 +196,17 @@ namespace Rtt return false; Format fmt = bitmap->GetFormat(); + + // A captured frame is tagged kBGRA but lands in memory as A,R,G,B (packed + // readback, little-endian). The writers below take byte order, so describe it + // as it is, or red and green come back swapped and blue from the alpha byte. +#ifndef Rtt_BIG_ENDIAN + if (fmt == PlatformBitmap::kBGRA) + { + fmt = PlatformBitmap::kARGB; + } +#endif + bool rc = false; std::string path = filePath; diff --git a/platform/shared/Rtt_BitmapUtils.cpp b/platform/shared/Rtt_BitmapUtils.cpp index c969ce6fd..1c612bfeb 100644 --- a/platform/shared/Rtt_BitmapUtils.cpp +++ b/platform/shared/Rtt_BitmapUtils.cpp @@ -169,10 +169,27 @@ namespace bitmapUtil break; } case Rtt::PlatformBitmap::Format::kABGR: - case Rtt::PlatformBitmap::Format::kARGB: Rtt_ASSERT(0); //todo break; + case Rtt::PlatformBitmap::Format::kARGB: + { + // convert to RGB + rgb.reset((uint8_t*)malloc(width * height * 3)); + uint8_t* src = data; + uint8_t* dst = rgb.get(); + for (int i = 0; i < width * height; i++) + { + dst[0] = src[1]; + dst[1] = src[2]; + dst[2] = src[3]; + dst += 3; + src += 4; + } + data = rgb.get(); + break; + } + case Rtt::PlatformBitmap::Format::kBGRA: { // convert to RGB @@ -400,6 +417,24 @@ namespace bitmapUtil data = rgba; free_data = true; } + else if (format == Rtt::PlatformBitmap::Format::kARGB) + { + // ARGB ==> RGBA + U8* rgba = (U8*)malloc(width * height * 4); + U8* src = data; + U8* dst = rgba; + for (int i = 0; i < width * height; i++) + { + dst[0] = src[1]; + dst[1] = src[2]; + dst[2] = src[3]; + dst[3] = src[0]; + dst += 4; + src += 4; + } + data = rgba; + free_data = true; + } for (int y = 0; y < height; y++) {