17bool g_filesystem_ready =
false;
18std::function<void(std::string)> g_rom_load_handler;
19std::queue<std::string> g_pending_rom_loads;
20std::mutex g_rom_load_mutex;
27void SetFileSystemReady() {
28 g_filesystem_ready =
true;
29 LOG_INFO(
"Wasm",
"Filesystem sync complete.");
33 if (Module.onFileSystemReady) {
34 Module.onFileSystemReady();
40void SyncFilesystem() {
43 if (typeof FS !==
'undefined' && FS.syncfs) {
44 FS.syncfs(false, function(err) {
46 console.error(
'[WASM] Failed to sync filesystem:', err);
48 console.log(
'[WASM] Filesystem synced successfully');
56void LoadRomFromWeb(
const char* filename) {
58 LOG_ERROR(
"Wasm",
"LoadRomFromWeb called with null filename");
62 std::string path(filename);
66 LOG_ERROR(
"Wasm",
"LoadRomFromWeb called with empty filename");
71 if (path.find(
"..") != std::string::npos) {
72 LOG_ERROR(
"Wasm",
"LoadRomFromWeb: path traversal not allowed: %s", filename);
77 if (path.length() > 512) {
78 LOG_ERROR(
"Wasm",
"LoadRomFromWeb: path too long (%zu chars)", path.length());
82 yaze::app::wasm::TriggerRomLoad(path);
87EM_JS(
void, MountFilesystems, (), {
99 directories.forEach(function(dir) {
104 if (e.code !==
'EEXIST') {
105 console.warn(
"Failed to create directory " + dir +
": " + e);
111 FS.mount(MEMFS, {},
'/temp');
115 if (typeof IDBFS !==
'undefined') {
117 }
else if (typeof Module !==
'undefined' && typeof Module.IDBFS !==
'undefined') {
118 idbfs = Module.IDBFS;
119 }
else if (typeof FS !==
'undefined' && typeof FS.filesystems !==
'undefined' && FS.filesystems.IDBFS) {
120 idbfs = FS.filesystems.IDBFS;
124 var persistentDirs = [
'/roms',
'/saves',
'/config',
'/projects',
'/prompts',
'/recent'];
125 var mountedCount = 0;
126 var totalToMount = persistentDirs.length;
128 if (idbfs !== null) {
129 persistentDirs.forEach(function(dir) {
131 FS.mount(idbfs, {}, dir);
134 console.error(
"Error mounting IDBFS for " + dir +
": " + e);
137 FS.mount(MEMFS, {}, dir);
146 FS.syncfs(
true, function(err) {
148 console.error(
"Failed to sync IDBFS: " + err);
150 console.log(
"IDBFS synced successfully");
153 Module._SetFileSystemReady();
157 console.warn(
"IDBFS not available, using MEMFS for all directories (no persistence)");
158 persistentDirs.forEach(function(dir) {
160 FS.mount(MEMFS, {}, dir);
165 Module._SetFileSystemReady();
169EM_JS(
void, SetupYazeGlobalApi, (), {
170 if (typeof Module ===
'undefined')
return;
174 execute: function(cmd) {
175 if (Module.executeCommand) {
176 return Module.executeCommand(cmd);
178 return "Error: bindings not ready";
181 getState: function() {
182 if (Module.getFullDebugState) {
183 try {
return JSON.parse(Module.getFullDebugState()); }
catch(e) {
return {}; }
189 if (Module.getEditorState) {
190 try {
return JSON.parse(Module.getEditorState()); }
catch(e) {
return {}; }
195 loadRom: function(filename) {
196 return this.execute(
"rom load " + filename);
200 console.log(
"[yaze] window.yazeApp API initialized for agents");
203namespace yaze::app::wasm {
205bool IsFileSystemReady() {
206 return g_filesystem_ready;
209void SetRomLoadHandler(std::function<
void(std::string)> handler) {
210 std::lock_guard<std::mutex> lock(g_rom_load_mutex);
211 g_rom_load_handler = handler;
214 while (!g_pending_rom_loads.empty()) {
215 std::string path = g_pending_rom_loads.front();
216 g_pending_rom_loads.pop();
217 LOG_INFO(
"Wasm",
"Flushing pending ROM load: %s", path.c_str());
222void TriggerRomLoad(
const std::string& path) {
223 std::lock_guard<std::mutex> lock(g_rom_load_mutex);
224 if (g_rom_load_handler) {
225 g_rom_load_handler(path);
227 LOG_INFO(
"Wasm",
"Queuing ROM load (handler not ready): %s", path.c_str());
228 g_pending_rom_loads.push(path);
232void InitializeWasmPlatform() {
234 app::platform::WasmConfig::Get().LoadFromJavaScript();
237 SetupYazeGlobalApi();
240 auto& drop_handler = yaze::platform::WasmDropHandler::GetInstance();
241 drop_handler.Initialize(
"",
242 [](
const std::string& filename,
const std::vector<uint8_t>& data) {
244 std::string ext = filename.substr(filename.find_last_of(
".") + 1);
245 std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
247 if (ext ==
"sfc" || ext ==
"smc" || ext ==
"zip") {
249 std::string path =
"/roms/" + filename;
250 std::ofstream file(path, std::ios::binary);
251 file.write(
reinterpret_cast<const char*
>(data.data()), data.size());
254 LOG_INFO(
"Wasm",
"Wrote dropped ROM to %s (%zu bytes)", path.c_str(), data.size());
255 LoadRomFromWeb(path.c_str());
257 else if (ext ==
"pal" || ext ==
"tpl") {
258 LOG_INFO(
"Wasm",
"Palette drop detected: %s. Feature pending UI integration.", filename.c_str());
261 [](
const std::string& error) {
262 LOG_ERROR(
"Wasm",
"Drop Handler Error: %s", error.c_str());
#define LOG_ERROR(category, format,...)
#define LOG_INFO(category, format,...)
EM_JS(void, CallJsAiDriver,(const char *history_json), { if(window.yaze &&window.yaze.ai &&window.yaze.ai.processAgentRequest) { window.yaze.ai.processAgentRequest(UTF8ToString(history_json));} else { console.error("AI Driver not found in window.yaze.ai.processAgentRequest");} })
std::string getEditorState()