bool vm_shutdown() { if (gLuaState != NULL) { vm_rewind(); lua_close(gLuaState); vm_info("shutdown success"); return true; } else { vm_info("shutdown failed"); return false; } }
bool vm_init() { gLuaState = luaL_newstate(); if (gLuaState != NULL) { // Load lua libraries const luaL_Reg *lib; for (lib = loadedlibs; lib->func; lib++) { luaL_requiref(gLuaState, lib->name, lib->func, 1); lua_pop(gLuaState, 1); /* remove lib */ } // Override lua's builtin require function lua_getglobal(gLuaState, "_G"); lua_pushcfunction(gLuaState, luax_require); lua_setfield(gLuaState, -2, "require"); vm_rewind(); // Set the error handler at stack offset 1 lua_pushcfunction(gLuaState, internal_handle_error); errorHandlerStackIndex = lua_gettop(gLuaState); // Load bootstrap code internal_execute_script((char*)src_boot_lua, src_boot_lua_len, "<boot>", false); // Setup console vm_global_get("console"); vm_field_set_function("log", console_log); vm_field_set_function("info", console_info); vm_field_set_function("warn", console_warn); vm_field_set_function("error", console_error); vm_global_get("game"); vm_field_set_function("test", test); vm_rewind(); assert(lua_gettop(gLuaState) == 1); vm_info("init success"); return true; } else { vm_info("init failed to create lua state"); return false; } }
void vm_rewind() { const int count = lua_gettop(gLuaState) - errorHandlerStackIndex; if (count > 0) { vm_info("dropping %d stack entries", count); lua_pop(gLuaState, count); } assert(lua_gettop(gLuaState) == errorHandlerStackIndex); }
static bool internal_require_file(const char *filename, const bool wasRequired) { IOResource *text; text = io_load_text(filename); if (text == NULL) { vm_error("script '%s' not found", filename); return false; } else { vm_info("script '%s' loaded", filename); return internal_execute_script(text->handle, text->size, text->filename, wasRequired); } }
static bool internal_execute_script(const char *buf, unsigned int len, const char *filename, const bool wasRequired) { luaL_loadbuffer(gLuaState, buf, len, filename); if (lua_pcall(gLuaState, 0, 1, errorHandlerStackIndex) != LUA_OK) { vm_rewind(); return false; } else { vm_info("script '%s' executed", filename); if (!wasRequired) { lua_pop(gLuaState, 1); // -1 } return true; } }
bool vm_write_nbytes(VMState *state, VMStateDiff *diff, VMInfoType type, size_t destaddr, BIGTYPE value, int nbytes) { char *location; VMSingleStateDiff *singlediff; if (!(location = _get_location(state, type, destaddr, NULL))) goto error; if (diff) { /* update our diffs */ err_malloc((singlediff = malloc(sizeof(VMSingleStateDiff)))); /* We already did error checking, don't do it again. Read and store in host endianness so rstep can write to uC endianness. */ singlediff->oldval = vm_info(state, type, destaddr, NULL); #ifdef VM_DEBUG singlediff->newval = value; #endif singlediff->type = type; singlediff->location = destaddr; singlediff->nbytes = nbytes; singlediff->next = diff->singlediff; diff->singlediff = singlediff; } /* finally, write the value */ vm_convert_endianness((char *) &value, nbytes); memcpy(location, &value, nbytes); return true; error: return false; }
bool vm_update() { vm_info("update"); return true; }