sdl_runtime_compiler git · main
SDL3 game for running and compiling code at runtime
C++ 72.3% C 26.2%git clone https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler.gitwget https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler/archive/sdl_runtime_compiler.tar.gzCleanup
CMakeLists.txt | 5 ---- assets/sandbox.c | 5 ++-- assets/sandbox.c.last_ok | 3 +-- src/core/game.cpp | 16 +++++++++++++ src/entities/player.cpp | 6 ++--- src/entities/player.hpp | 4 ++++ src/states/game_state.cpp | 16 ++++++++++++- src/systems/compiler_system.cpp | 51 ++++----------------------------------- src/systems/mod_loader.cpp | 4 +++- src/utils/ascii.hpp | 53 +++++++++++++++++++++++++++++++++++++++++ 10 files changed, 101 insertions(+), 62 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b138ec..38dedb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,11 +135,6 @@ add_custom_target(compile_commands_link ALL DEPENDS SDL3_RuntimeCompiler ) -add_custom_command(TARGET SDL3_RuntimeCompiler POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory /tmp/game_mod_include - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_SOURCE_DIR}/src/systems/game_mod_abi.h - /tmp/game_mod_include/game_mod_abi.h) # ───────────────────────────────────────────────────────────────────────────── # Benchmarks diff --git a/assets/sandbox.c b/assets/sandbox.c index e596933..5e72631 100644 --- a/assets/sandbox.c +++ b/assets/sandbox.c @@ -1,4 +1,4 @@ -#include "game_mod_abi.h" +# include "game_mod_abi.h" static int n ; static ModObject * o ; static void box ( double x , double y , double z , double hx , double hy , double hz ) { @@ -19,10 +19,9 @@ n = n + 1 ; } int game_build ( ModObject * out , int max ) { ( void ) max ; - o = out ; n = 0 ; box ( 0 , - 16 , 5 , 1 , 1 , 1 ) ; text ( 0 , - 15 , 5 , "hi" ) ; -box ( 3 , - 16 , 5 , 1 , 2 , 1 ) ; +box ( 3 , - 16 , 5 , 1 , 6 , 1 ) ; return n ; } diff --git a/assets/sandbox.c.last_ok b/assets/sandbox.c.last_ok index b966a3c..5e72631 100644 --- a/assets/sandbox.c.last_ok +++ b/assets/sandbox.c.last_ok @@ -22,7 +22,6 @@ int game_build ( ModObject * out , int max ) { o = out ; n = 0 ; box ( 0 , - 16 , 5 , 1 , 1 , 1 ) ; text ( 0 , - 15 , 5 , "hi" ) ; -box(6,-16,5,1,3,1); -box ( 3 , - 16 , 7 , 1 , 2 , 1 ) ; +box ( 3 , - 16 , 5 , 1 , 6 , 1 ) ; return n ; } diff --git a/src/core/game.cpp b/src/core/game.cpp index af565aa..fbcd20e 100644 --- a/src/core/game.cpp +++ b/src/core/game.cpp @@ -1,3 +1,6 @@ +#include <filesystem> +#include <system_error> + #include "game.hpp" #include "utils/config.hpp" #include "entities/world.hpp" @@ -14,6 +17,19 @@ Game::~Game() = default; bool Game::init() { + { + std::error_code ec; + std::filesystem::create_directories("/tmp/game_mod_include", ec); + std::filesystem::copy_file( + "src/systems/game_mod_abi.h", + "/tmp/game_mod_include/game_mod_abi.h", + std::filesystem::copy_options::overwrite_existing, ec); + if (ec) + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Could not stage game_mod_abi.h: %s", ec.message().c_str()); + } + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); diff --git a/src/entities/player.cpp b/src/entities/player.cpp index 5ec4508..179db30 100644 --- a/src/entities/player.cpp +++ b/src/entities/player.cpp @@ -56,10 +56,8 @@ Player::compute_Movement(const FrameInput& input) if (n != 0) { double inv = 1.0 / SDL_sqrt(n); - double mult = 60.0; - - acc_x = mult * ( c*dirX + s*dirZ) * inv; - acc_z = mult * (-s*dirX + c*dirZ) * inv; + acc_x = MOVE_ACCEL * ( c*dirX + s*dirZ) * inv; + acc_z = MOVE_ACCEL * (-s*dirX + c*dirZ) * inv; } } diff --git a/src/entities/player.hpp b/src/entities/player.hpp index e7ce60a..27fbff5 100644 --- a/src/entities/player.hpp +++ b/src/entities/player.hpp @@ -32,6 +32,10 @@ public: float radius {0.5f}; float height {1.5f}; bool on_ground{false}; + static constexpr double + JUMP_VELOCITY = 8.4375; + static constexpr double + MOVE_ACCEL = 60.0; void compute_Movement(const FrameInput& input); void add_Look(int dx, int dy); diff --git a/src/states/game_state.cpp b/src/states/game_state.cpp index dc15ac0..906f29b 100644 --- a/src/states/game_state.cpp +++ b/src/states/game_state.cpp @@ -338,7 +338,7 @@ void GameState::on_Jump() { if (ctx.player->on_ground) { - ctx.player->vel.y = 8.4375; + ctx.player->vel.y = Player::JUMP_VELOCITY; ctx.player->on_ground = false; } } @@ -880,8 +880,22 @@ GameState::scene_Teardown() ctx.scenery.end()); } + // Also drop any dynamic-lib spawned objects (boxes in scenery, text in words). + if (!mod_scenery.empty()) { + std::unordered_set<GameObject*> mod_set(mod_scenery.begin(), mod_scenery.end()); + ctx.scenery.erase( + std::remove_if(ctx.scenery.begin(), ctx.scenery.end(), + [&mod_set](const GameObjectPtr& sp){ return mod_set.count(sp.get()) > 0; }), + ctx.scenery.end()); + ctx.words.erase( + std::remove_if(ctx.words.begin(), ctx.words.end(), + [&mod_set](const Text3dPtr& wp){ return mod_set.count(wp.get()) > 0; }), + ctx.words.end()); + } + step_scenery.clear(); step_plates.clear(); + mod_scenery.clear(); } diff --git a/src/systems/compiler_system.cpp b/src/systems/compiler_system.cpp index 4e4e3dc..a0375fe 100644 --- a/src/systems/compiler_system.cpp +++ b/src/systems/compiler_system.cpp @@ -1,49 +1,8 @@ -#include "systems/compiler_system.hpp" -#include "text_3d/text_3d.hpp" #include <SDL3/SDL.h> - - - -static std::string -sanitize_Ascii(const std::string& in) -{ - std::string out; - out.reserve(in.size()); - - size_t i = 0; - while (i < in.size()) { - unsigned char c = static_cast<unsigned char>(in[i]); - - if (c < 0x80) { - // Plain ASCII — keep as-is - out += static_cast<char>(c); - i++; - } - else if (c == 0xE2 && i+2 < in.size() - && static_cast<unsigned char>(in[i+1]) == 0x80) { - // Common Unicode punctuation block U+2000–U+20FF - unsigned char c3 = static_cast<unsigned char>(in[i+2]); - switch (c3) { - case 0x98: case 0x99: out += '\''; break; // ' ' - case 0x9C: case 0x9D: out += '"'; break; // " " - case 0x93: case 0x94: out += '"'; break; // " " - case 0xA2: out += '-'; break; // – - case 0xA6: out += '-'; break; // — - default: out += '?'; break; - } - i += 3; - } - else { - // Skip other multi-byte sequences - out += '?'; - while (i < in.size() && (static_cast<unsigned char>(in[i]) & 0xC0) == 0x80) - i++; - if (i < in.size()) i++; - } - } - return out; -} +#include "systems/compiler_system.hpp" +#include "text_3d/text_3d.hpp" +#include "utils/ascii.hpp" @@ -67,7 +26,7 @@ CompilerSystem::compile(TextWallList& texts, const std::string& src) // Open gcc pipe — stderr redirected to stdout so we get errors too if (pipe) { pclose(pipe); pipe = nullptr; } - pipe = popen("gcc /tmp/game_prog.c -o /tmp/game_prog 2>&1", "r"); + pipe = popen("LC_ALL=C gcc /tmp/game_prog.c -o /tmp/game_prog 2>&1", "r"); if (!pipe) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CompilerSystem: popen failed"); } @@ -109,7 +68,7 @@ CompilerSystem::push_Line(TextWallList& texts, const std::string& line, float wo { if (line == "OK") last_compile_ok = true; - std::string clean = sanitize_Ascii(line); + std::string clean = ascii_Sanitize(line); for (TextWallPtr& wt : texts) if (wt->role == Wall::Role::Compiler) diff --git a/src/systems/mod_loader.cpp b/src/systems/mod_loader.cpp index f0e8d53..9adcd93 100644 --- a/src/systems/mod_loader.cpp +++ b/src/systems/mod_loader.cpp @@ -6,6 +6,7 @@ #include "systems/mod_loader.hpp" #include "text_3d/text_3d.hpp" +#include "utils/ascii.hpp" // Where game_mod_abi.h is installed at runtime, and the build scratch dir. @@ -151,7 +152,8 @@ ModLoader::push_Line(TextWallList& texts, const std::string& line, float world_s Vec3 pos = tf.position; pos.y = start_y; - Text3dPtr t = make_Text3d(line, Text3d::depth_compiler, 0.003f, + std::string clean = ascii_Sanitize(line); + Text3dPtr t = make_Text3d(clean, Text3d::depth_compiler, 0.003f, pos, Text3d::color_compiler); t->yaw = tf.yaw; diff --git a/src/utils/ascii.hpp b/src/utils/ascii.hpp new file mode 100644 index 0000000..bc5a66a --- /dev/null +++ b/src/utils/ascii.hpp @@ -0,0 +1,53 @@ +#pragma once +#include <string> + +// ───────────────────────────────────────────────────────────────────────── +// ascii_Sanitize — collapse non-ASCII bytes to safe ASCII for wall display. +// +// gcc diagnostics use Unicode directional quotes (U+2018/2019 ‘ ’, U+201C/201D +// “ ”) which the text renderer can't draw. This maps the common ones to plain +// ' and ", and replaces any other multibyte sequence with '?'. Used by both +// CompilerSystem and ModLoader so their wall output stays renderable. +// +// Note: also set LC_ALL=C on the gcc invocation to make gcc emit ASCII quotes +// at the source; this function is the belt-and-suspenders fallback. +// ───────────────────────────────────────────────────────────────────────── +inline std::string +ascii_Sanitize(const std::string& in) +{ + std::string out; + out.reserve(in.size()); + + size_t i = 0; + while (i < in.size()) { + const unsigned char c = static_cast<unsigned char>(in[i]); + + if (c < 0x80) { + out += static_cast<char>(c); + ++i; + continue; + } + + // U+2000–U+20FF punctuation block: E2 80 xx + if (c == 0xE2 && i + 2 < in.size() && + static_cast<unsigned char>(in[i + 1]) == 0x80) { + const unsigned char c3 = static_cast<unsigned char>(in[i + 2]); + switch (c3) { + case 0x98: case 0x99: out += '\''; break; // ‘ ’ + case 0x9C: case 0x9D: out += '"'; break; // “ ” + case 0x93: case 0x94: out += '-'; break; // – — + default: out += '\''; break; + } + i += 3; + continue; + } + + // Any other multibyte sequence: one '?', skip continuation bytes. + out += '?'; + ++i; + while (i < in.size() && + (static_cast<unsigned char>(in[i]) & 0xC0) == 0x80) + ++i; + } + return out; +}