// ============================================================================ // LUA GAME LOADER - EMULATOR IMPLEMENTATION // ============================================================================ // Discovers Lua scripts from filesystem and integrates with game launcher #include "../games/lua_game_loader.h" #include "../games/lua_game.h" #include #include #include #include #include #include #include namespace fs = std::filesystem; // Structure to hold script path for factory closure struct LuaGameFactoryData { char script_path[256]; }; static std::vector factory_data_list; bool LuaGameLoader::parse_metadata(const char* script_path, char* name, char* description) { // Default name from filename fs::path path(script_path); std::string filename = path.stem().string(); // Get filename without extension strncpy(name, filename.c_str(), 63); name[63] = '\0'; // Default empty description description[0] = '\0'; // Try to open file and parse metadata comments std::ifstream file(script_path); if (!file.is_open()) { printf("LuaGameLoader: Warning - could not open %s for metadata\n", script_path); return false; } // Read first 512 bytes to look for metadata comments char buffer[512]; file.read(buffer, sizeof(buffer) - 1); std::streamsize bytes_read = file.gcount(); file.close(); if (bytes_read == 0) { return false; } buffer[bytes_read] = '\0'; // Parse metadata comments: -- NAME: Game Name char* line = buffer; while (line && (line - buffer) < bytes_read) { char* next_line = strchr(line, '\n'); if (next_line) *next_line = '\0'; // Check for -- NAME: if (strncmp(line, "-- NAME:", 8) == 0) { const char* value = line + 8; while (*value == ' ') value++; // Skip spaces strncpy(name, value, 63); name[63] = '\0'; } // Check for -- DESC: else if (strncmp(line, "-- DESC:", 8) == 0) { const char* value = line + 8; while (*value == ' ') value++; strncpy(description, value, 127); description[127] = '\0'; } if (next_line) { line = next_line + 1; } else { break; } } return true; } int LuaGameLoader::register_all_games(GameLauncher* launcher) { int count = 0; printf("LuaGameLoader: Scanning games/lua_examples directory for .lua scripts...\n"); // Path to lua examples relative to emulator binary const char* search_paths[] = { "../games/lua_examples", "games/lua_examples", "./lua_examples" }; fs::path games_dir; bool found_dir = false; // Try to find the lua_examples directory for (const char* search_path : search_paths) { if (fs::exists(search_path) && fs::is_directory(search_path)) { games_dir = fs::path(search_path); found_dir = true; break; } } if (!found_dir) { printf("LuaGameLoader: Could not find games/lua_examples directory\n"); printf("LuaGameLoader: Tried: ../games/lua_examples, games/lua_examples, ./lua_examples\n"); return 0; } printf("LuaGameLoader: Found directory: %s\n", games_dir.string().c_str()); // Scan for .lua files try { for (const auto& entry : fs::directory_iterator(games_dir)) { if (!entry.is_regular_file()) continue; // Check for .lua extension if (entry.path().extension() != ".lua") continue; std::string script_path = entry.path().string(); // Parse metadata char name[64]; char description[128]; parse_metadata(script_path.c_str(), name, description); printf("LuaGameLoader: Found %s - '%s'\n", entry.path().filename().string().c_str(), name); // Create factory data (persistent for game lifetime) LuaGameFactoryData* data = new LuaGameFactoryData(); strncpy(data->script_path, script_path.c_str(), sizeof(data->script_path) - 1); data->script_path[sizeof(data->script_path) - 1] = '\0'; factory_data_list.push_back(data); // Register with launcher - using lambda factory pattern launcher->register_game( name, description[0] ? description : "Lua Script", [data](uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui, InputManager* input_manager) -> Game* { return new LuaGame(data->script_path, width, height, renderer, gui, input_manager); } ); count++; } } catch (const fs::filesystem_error& e) { printf("LuaGameLoader: Error scanning directory: %s\n", e.what()); return count; } printf("LuaGameLoader: Registered %d Lua games\n", count); return count; }