Fry3DX 0.5: builds for Windows, Linux and Android, a phone layout, Apache 2.0

- Apache License 2.0
- Windows: cross-built with clang-cl (cmake --preset windows), a window
  program with its icon; Linux: a portable preset (SDL and the C++
  library inside); Android: android/build_apk.py makes the APK
- tools/package.py packs the downloads; a GitHub workflow builds all
  three and makes a release for a v* tag
- A phone layout (fry_touch, on by default on Android): the UI drawn
  bigger, panels when asked for, a bar of big buttons, one finger to
  turn the view, two to move and pinch, a long press for a right-click;
  files through the phone's file picker
- Settings and autosaves now in a Nexoniarz folder (copied over once)
- README rewritten, the website shows the downloads and the phone

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMSrd5oe1GpUD7E6d825KP
This commit is contained in:
Nexoniarz 2026-10-19 22:05:01 +02:00
commit f6f5e5f288
40 changed files with 1180 additions and 158 deletions

View file

@ -312,13 +312,7 @@ int runClient(Game& game) {
window.setIcon(px, w, h);
stbi_image_free(px);
}
} else if (auto data = fs::read("branding/keel_emblem.yapf"))
if (yapf_texture_t* tex = yapf_tex_load_memory(data->data(), data->size(), 0, 1, nullptr)) {
std::vector<uint8_t> rgba(size_t(tex->width) * tex->height * 4);
if (yapf_tex_to_rgba8(tex, yapf_tex_surface(tex, 0, 0, 0, 0), 0, rgba.data()) == YAPF_OK)
window.setIcon(rgba.data(), int(tex->width), int(tex->height));
yapf_tex_free(tex);
}
}
if (!g_testMode) audio::init();
ui::init();
log::info("Press ` (tilde key) to open the console");
@ -539,17 +533,16 @@ int run(Game& game, int argc, char** argv) {
crash::install(g_prefPath, args, dog);
}
// Content: the engine's own (<exe dir>/keel/), then the game's (<exe dir>/<game>/) over it,
// Content: the engine's own (<exe dir>/engine/), then the game's (<exe dir>/<game>/) over it,
// each with its packs — like Source's hl2/ under a mod.
#if defined(__ANDROID__)
const std::string exeDir = unpackAndroidContent();
if (const char* cache = SDL_GetAndroidCachePath()) setenv("TMPDIR", cache, 1); // temp files (script modules) go there
const bool firstRun = !std::filesystem::exists(g_configPath);
if (const char* cache = SDL_GetAndroidCachePath()) setenv("TMPDIR", cache, 1); // temp files go there
#else
const char* base = SDL_GetBasePath();
const std::string exeDir = base ? base : "./";
#endif
if (!fs::mountGameDir(exeDir + "keel")) log::warn("Engine folder {}keel not found; fonts and UI won't load", exeDir);
if (!fs::mountGameDir(exeDir + "engine")) log::warn("Engine folder {}engine not found; fonts and UI won't load", exeDir);
const std::string gameDir = exeDir + game.name();
if (!fs::mountGameDir(gameDir)) log::warn("Game folder {} not found; no content will load", gameDir);
@ -558,9 +551,6 @@ int run(Game& game, int argc, char** argv) {
// Like Source's config_default.cfg: default binds/settings, then the player's own.
if (!g_dedicated && fs::exists("cfg/default.cfg")) execute("exec default.cfg");
if (std::filesystem::exists(g_configPath)) execute("exec \"" + g_configPath + "\"");
#if defined(__ANDROID__)
if (firstRun) execute("preset Low"); // a phone: start light (the options change it)
#endif
if (fs::exists("cfg/autoexec.cfg")) execute("exec autoexec.cfg");
executeCommandLine(startup, 0);
g_modsDir = exeDir + "mods/" + game.name();