bool Convert(const VfsPath& daeFilename, const VfsPath& pmdFilename, CColladaManager::FileType type) { // To avoid always loading the DLL when it's usually not going to be // used (and to do the same on Linux where delay-loading won't help), // and to avoid compile-time dependencies (because it's a minor pain // to get all the right libraries to build the COLLADA DLL), we load // it dynamically when it is required, instead of using the exported // functions and binding at link-time. if (!dll.IsLoaded()) { if (!TryLoadDLL()) return false; if (!LoadSkeletonDefinitions()) { dll.Unload(); // Error should have been logged already return false; } } // Set the filename for the logger to report set_logger(ColladaLog, const_cast<void*>(static_cast<const void*>(&daeFilename))); // We need to null-terminate the buffer, so do it (possibly inefficiently) // by converting to a CStr CStr daeData; { CVFSFile daeFile; if (daeFile.Load(m_VFS, daeFilename) != PSRETURN_OK) return false; daeData = daeFile.GetAsString(); } // Do the conversion into a memory buffer // We need to check the result, as archive builder needs to know if the source dae // was sucessfully converted to .pmd/psa int result = -1; WriteBuffer writeBuffer; switch (type) { case CColladaManager::PMD: result = convert_dae_to_pmd(daeData.c_str(), ColladaOutput, &writeBuffer); break; case CColladaManager::PSA: result = convert_dae_to_psa(daeData.c_str(), ColladaOutput, &writeBuffer); break; } // don't create zero-length files (as happens in test_invalid_dae when // we deliberately pass invalid XML data) because the VFS caching // logic warns when asked to load such. if (writeBuffer.Size()) { Status ret = m_VFS->CreateFile(pmdFilename, writeBuffer.Data(), writeBuffer.Size()); ENSURE(ret == INFO::OK); } return (result == 0); }
bool BeginAtlas(const CmdLineArgs& args, const DllLoader& dll) { // Load required symbols from the DLL try { dll.LoadSymbol("Atlas_StartWindow", Atlas_StartWindow); dll.LoadSymbol("Atlas_SetMessagePasser", Atlas_SetMessagePasser); dll.LoadSymbol("Atlas_SetDataDirectory", Atlas_SetDataDirectory); dll.LoadSymbol("Atlas_SetConfigDirectory", Atlas_SetConfigDirectory); dll.LoadSymbol("Atlas_GLSetCurrent", Atlas_GLSetCurrent); dll.LoadSymbol("Atlas_GLSwapBuffers", Atlas_GLSwapBuffers); dll.LoadSymbol("Atlas_NotifyEndOfFrame", Atlas_NotifyEndOfFrame); dll.LoadSymbol("Atlas_DisplayError", Atlas_DisplayError); dll.LoadSymbol("Atlas_ReportError", Atlas_ReportError); dll.LoadSymbol("ShareableMalloc", ShareableMallocFptr); dll.LoadSymbol("ShareableFree", ShareableFreeFptr); } catch (PSERROR_DllLoader&) { debug_warn(L"Failed to initialise DLL"); return false; } // Construct a message passer for communicating with Atlas // (here so that its scope lasts beyond the game thread) MessagePasserImpl msgPasser; AtlasMessage::g_MessagePasser = &msgPasser; // Pass our message handler to Atlas Atlas_SetMessagePasser(&msgPasser); // Tell Atlas the location of the data directory const Paths paths(args); Atlas_SetDataDirectory(paths.RData().string().c_str()); // Tell Atlas the location of the user config directory Atlas_SetConfigDirectory(paths.Config().string().c_str()); // Run the engine loop in a new thread pthread_t engineThread; pthread_create(&engineThread, NULL, RunEngine, reinterpret_cast<void*>(const_cast<CmdLineArgs*>(&args))); // Start Atlas UI on main thread // (required for wxOSX/Cocoa compatibility - see http://trac.wildfiregames.com/ticket/500) Atlas_StartWindow(L"ScenarioEditor"); // Wait for the engine to exit pthread_join(engineThread, NULL); // TODO: delete all remaining messages, to avoid memory leak warnings // Restore main thread ThreadUtil::SetMainThread(); // Clean up AtlasView::DestroyViews(); AtlasMessage::g_MessagePasser = NULL; return true; }
int DllLoader::ResolveName(const char *sName, char* sFunction, void **fixup) { DllLoader* pDll = (DllLoader*) DllLoaderContainer::GetModule(sName); if (pDll) { Export* pExp = pDll->GetExportByFunctionName(sFunction); if(pExp) { if (m_bTrack && pExp->track_function) *fixup = (void*)(pExp->track_function); else *fixup = (void*)(pExp->function); return 1; } } return 0; }
const char* DllLoader::ResolveReferencedDll(const char* dll) { DllLoader* pDll = (DllLoader*) DllLoaderContainer::LoadModule(dll, GetPath(), m_bLoadSymbols); if (!pDll) { CLog::Log(LOGDEBUG, "Unable to load referenced dll %s - Dll: %s", dll, GetFileName()); return NULL; } else if (!pDll->IsSystemDll()) { LoadedList* entry=new LoadedList; entry->pDll=pDll; entry->pNext=m_pDlls; m_pDlls=entry; } return pDll->GetFileName(); }
int DllLoader::ResolveOrdinal(const char *sName, unsigned long ordinal, void **fixup) { DllLoader* pDll = (DllLoader*) DllLoaderContainer::GetModule(sName); if (pDll) { Export* pExp = pDll->GetExportByOrdinal(ordinal); if(pExp) { if (m_bTrack && pExp->track_function) *fixup = (void*)(pExp->track_function); else *fixup = (void*)(pExp->function); return 1; } } return 0; }
bool TryLoadDLL() { if (!dll.LoadDLL()) { LOGERROR("Failed to load COLLADA conversion DLL"); return false; } try { dll.LoadSymbol("set_logger", set_logger); dll.LoadSymbol("set_skeleton_definitions", set_skeleton_definitions); dll.LoadSymbol("convert_dae_to_pmd", convert_dae_to_pmd); dll.LoadSymbol("convert_dae_to_psa", convert_dae_to_psa); } catch (PSERROR_DllLoader&) { LOGERROR("Failed to load symbols from COLLADA conversion DLL"); dll.Unload(); return false; } return true; }
// starts the Atlas UI. static void ATLAS_Run(const CmdLineArgs& args, int flags = 0) { // first check if we can run at all if(!atlas_dll.LoadDLL()) { if(flags & ATLAS_NO_GUI) DEBUG_DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested."); else DEBUG_DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");// TODO: implement GUI error message return; } // TODO (make nicer) extern bool BeginAtlas(const CmdLineArgs& args, const DllLoader& dll); if (!BeginAtlas(args, atlas_dll)) { debug_warn(L"Atlas loading failed"); return; } }
Status ReloadChangedFile(const VfsPath& path) { // Ignore files that aren't in the right path if (!boost::algorithm::starts_with(path.string(), L"art/skeletons/")) return INFO::OK; if (path.Extension() != L".xml") return INFO::OK; m_skeletonHashInvalidated = true; // If the file doesn't exist (e.g. it was deleted), don't bother reloading // or 'unloading' since that isn't possible if (!VfsFileExists(path)) return INFO::OK; if (!dll.IsLoaded() && !TryLoadDLL()) return ERR::FAIL; LOGMESSAGE("Hotloading skeleton definitions from '%s'", path.string8()); // Set the filename for the logger to report set_logger(ColladaLog, const_cast<void*>(static_cast<const void*>(&path))); CVFSFile skeletonFile; if (skeletonFile.Load(m_VFS, path) != PSRETURN_OK) { LOGERROR("Failed to read skeleton defintions from '%s'", path.string8()); return ERR::FAIL; } int ok = set_skeleton_definitions((const char*)skeletonFile.GetBuffer(), (int)skeletonFile.GetBufferSize()); if (ok < 0) { LOGERROR("Failed to load skeleton definitions from '%s'", path.string8()); return ERR::FAIL; } return INFO::OK; }
bool Convert(const VfsPath& daeFilename, const VfsPath& pmdFilename, CColladaManager::FileType type) { // To avoid always loading the DLL when it's usually not going to be // used (and to do the same on Linux where delay-loading won't help), // and to avoid compile-time dependencies (because it's a minor pain // to get all the right libraries to build the COLLADA DLL), we load // it dynamically when it is required, instead of using the exported // functions and binding at link-time. if (! dll.IsLoaded()) { if (! dll.LoadDLL()) { LOGERROR(L"Failed to load COLLADA conversion DLL"); return false; } try { dll.LoadSymbol("set_logger", set_logger); dll.LoadSymbol("set_skeleton_definitions", set_skeleton_definitions); dll.LoadSymbol("convert_dae_to_pmd", convert_dae_to_pmd); dll.LoadSymbol("convert_dae_to_psa", convert_dae_to_psa); } catch (PSERROR_DllLoader&) { LOGERROR(L"Failed to load symbols from COLLADA conversion DLL"); dll.Unload(); return false; } VfsPath skeletonPath("art/skeletons/skeletons.xml"); // Set the filename for the logger to report set_logger(ColladaLog, static_cast<void*>(&skeletonPath)); CVFSFile skeletonFile; if (skeletonFile.Load(g_VFS, skeletonPath) != PSRETURN_OK) { LOGERROR(L"Failed to read skeleton definitions"); dll.Unload(); return false; } int ok = set_skeleton_definitions((const char*)skeletonFile.GetBuffer(), (int)skeletonFile.GetBufferSize()); if (ok < 0) { LOGERROR(L"Failed to load skeleton definitions"); dll.Unload(); return false; } // TODO: the cached PMD/PSA files should probably be invalidated when // the skeleton definition file is changed, else people will get confused // as to why it's not picking up their changes } // Set the filename for the logger to report set_logger(ColladaLog, const_cast<void*>(static_cast<const void*>(&daeFilename))); // We need to null-terminate the buffer, so do it (possibly inefficiently) // by converting to a CStr CStr daeData; { CVFSFile daeFile; if (daeFile.Load(g_VFS, daeFilename) != PSRETURN_OK) return false; daeData = daeFile.GetAsString(); } // Do the conversion into a memory buffer WriteBuffer writeBuffer; switch (type) { case CColladaManager::PMD: convert_dae_to_pmd(daeData.c_str(), ColladaOutput, &writeBuffer); break; case CColladaManager::PSA: convert_dae_to_psa(daeData.c_str(), ColladaOutput, &writeBuffer); break; } // don't create zero-length files (as happens in test_invalid_dae when // we deliberately pass invalid XML data) because the VFS caching // logic warns when asked to load such. if (writeBuffer.Size()) { Status ret = g_VFS->CreateFile(pmdFilename, writeBuffer.Data(), writeBuffer.Size()); ENSURE(ret == INFO::OK); } return true; }
~CColladaManagerImpl() { if (dll.IsLoaded()) set_logger(NULL, NULL); // unregister the log handler }
bool BeginAtlas(const CmdLineArgs& args, const DllLoader& dll) { // Load required symbols from the DLL try { dll.LoadSymbol("Atlas_StartWindow", Atlas_StartWindow); dll.LoadSymbol("Atlas_SetMessagePasser", Atlas_SetMessagePasser); dll.LoadSymbol("Atlas_SetDataDirectory", Atlas_SetDataDirectory); dll.LoadSymbol("Atlas_GLSetCurrent", Atlas_GLSetCurrent); dll.LoadSymbol("Atlas_GLSwapBuffers", Atlas_GLSwapBuffers); dll.LoadSymbol("Atlas_NotifyEndOfFrame", Atlas_NotifyEndOfFrame); dll.LoadSymbol("Atlas_DisplayError", Atlas_DisplayError); dll.LoadSymbol("Atlas_ReportError", Atlas_ReportError); dll.LoadSymbol("ShareableMalloc", ShareableMallocFptr); dll.LoadSymbol("ShareableFree", ShareableFreeFptr); } catch (PSERROR_DllLoader&) { debug_warn(L"Failed to initialise DLL"); return false; } // Construct a message passer for communicating with Atlas MessagePasserImpl msgPasser; AtlasMessage::g_MessagePasser = &msgPasser; // Pass our message handler to Atlas Atlas_SetMessagePasser(&msgPasser); // Tell Atlas the location of the data directory const Paths paths(args); Atlas_SetDataDirectory(paths.RData().string().c_str()); // Register all the handlers for message which might be passed back RegisterHandlers(); // Create a new thread, and launch the Atlas window inside that thread const wchar_t* windowName = FindWindowName(args); pthread_t uiThread; pthread_create(&uiThread, NULL, LaunchWindow, reinterpret_cast<void*>(const_cast<wchar_t*>(windowName))); // Override ah_display_error to pass all errors to the Atlas UI AppHooks hooks = {0}; hooks.display_error = AtlasDisplayError; app_hooks_update(&hooks); // Disable the game's cursor rendering extern CStrW g_CursorName; g_CursorName = L""; state.args = args; state.running = true; state.view = View::GetView_None(); state.glCanvas = NULL; double last_activity = timer_Time(); while (state.running) { bool recent_activity = false; ////////////////////////////////////////////////////////////////////////// // (TODO: Work out why these things have to be in this order (to avoid // jumps when starting to move, etc)) // Calculate frame length { double time = timer_Time(); static double last_time = time; float length = (float)(time-last_time); last_time = time; ENSURE(length >= 0.0f); // TODO: filter out big jumps, e.g. when having done a lot of slow // processing in the last frame state.frameLength = length; } // Process the input that was received in the past if (g_Input.ProcessInput(&state)) recent_activity = true; ////////////////////////////////////////////////////////////////////////// { IMessage* msg; while ((msg = msgPasser.Retrieve()) != NULL) { recent_activity = true; std::string name (msg->GetName()); msgHandlers::const_iterator it = GetMsgHandlers().find(name); if (it != GetMsgHandlers().end()) { it->second(msg); } else { debug_warn(L"Unrecognised message"); // CLogger might not be initialised, but this error will be sent // to the debug output window anyway so people can still see it LOGERROR(L"Unrecognised message (%hs)", name.c_str()); } if (msg->GetType() == IMessage::Query) { // For queries, we need to notify MessagePasserImpl::Query // that the query has now been processed. sem_post((sem_t*) static_cast<QueryMessage*>(msg)->m_Semaphore); // (msg may have been destructed at this point, so don't use it again) // It's quite possible that the querier is going to do a tiny // bit of processing on the query results and then issue another // query, and repeat lots of times in a loop. To avoid slowing // that down by rendering between every query, make this // thread yield now. SDL_Delay(0); } else { // For non-queries, we need to delete the object, since we // took ownership of it. AtlasMessage::ShareableDelete(msg); } } } // Exit, if desired if (! state.running) break; ////////////////////////////////////////////////////////////////////////// // Do per-frame processing: ReloadChangedFiles(); RendererIncrementalLoad(); // Pump SDL events (e.g. hotkeys) SDL_Event_ ev; while (SDL_PollEvent(&ev.ev)) in_dispatch_event(&ev); if (g_GUI) g_GUI->TickObjects(); state.view->Update(state.frameLength); state.view->Render(); if (CProfileManager::IsInitialised()) g_Profiler.Frame(); double time = timer_Time(); if (recent_activity) last_activity = time; // Be nice to the processor (by sleeping lots) if we're not doing anything // useful, and nice to the user (by just yielding to other threads) if we are bool yield = (time - last_activity > 0.5); // But make sure we aren't doing anything interesting right now, where // the user wants to see the screen updating even though they're not // interacting with it if (state.view->WantsHighFramerate()) yield = false; if (yield) // if there was no recent activity... { double sleepUntil = time + 0.5; // only redraw at 2fps while (time < sleepUntil) { // To minimise latency when the user starts doing stuff, only // sleep for a short while, then check if anything's happened, // then go back to sleep // (TODO: This should probably be done with something like semaphores) Atlas_NotifyEndOfFrame(); // (TODO: rename to NotifyEndOfQuiteShortProcessingPeriodSoPleaseSendMeNewMessages or something) SDL_Delay(50); if (!msgPasser.IsEmpty()) break; time = timer_Time(); } } else { Atlas_NotifyEndOfFrame(); SDL_Delay(0); } } // TODO: delete all remaining messages, to avoid memory leak warnings // Wait for the UI to exit pthread_join(uiThread, NULL); // Clean up View::DestroyViews(); ScriptingHost::FinalShutdown(); return true; }
~CColladaManagerImpl() { if (dll.IsLoaded()) set_logger(NULL, NULL); // unregister the log handler UnregisterFileReloadFunc(ReloadChangedFileCB, this); }
ISimulation * SimulationFactory::CreateSimulation() { EventTriggerFactory::GetInstance()->Configure( EnvPtr->Config ); EventTriggerNodeFactory::GetInstance()->Configure( EnvPtr->Config ); EventTriggerCoordinatorFactory::GetInstance()->Configure( EnvPtr->Config ); NPFactory::CreateFactory(); IPFactory::CreateFactory(); ISimulation* newsim = nullptr; if ( CONFIG_PARAMETER_EXISTS( EnvPtr->Config, "Serialized_Population_Filenames" ) ) { std::string path("."); if ( CONFIG_PARAMETER_EXISTS( EnvPtr->Config, "Serialized_Population_Path" ) ) { path = GET_CONFIG_STRING(EnvPtr->Config, "Serialized_Population_Path"); } std::vector<string> filenames = GET_CONFIG_VECTOR_STRING( EnvPtr->Config, "Serialized_Population_Filenames" ); if ( filenames.size() != EnvPtr->MPI.NumTasks ) { throw IncoherentConfigurationException(__FILE__, __LINE__, __FUNCTION__, "MPI.NumTasks", float(EnvPtr->MPI.NumTasks), "filenames.size()", float(filenames.size()), "Number of serialized population filenames doesn't match number of MPI tasks."); } std::string population_filename = FileSystem::Concat(path, filenames[EnvPtr->MPI.Rank]); auto t_start = std::chrono::high_resolution_clock::now(); newsim = SerializedState::LoadSerializedSimulation( population_filename.c_str() ); auto t_finish = std::chrono::high_resolution_clock::now(); newsim->Initialize( EnvPtr->Config ); double elapsed = uint64_t((t_finish - t_start).count()) * 1000 * double(std::chrono::high_resolution_clock::period::num) / double(std::chrono::high_resolution_clock::period::den); LOG_INFO_F( "Loaded serialized population from '%s' in %f ms\n.", population_filename.c_str(), elapsed ); return newsim; } std::string sSimType; try { sSimType = GET_CONFIG_STRING(EnvPtr->Config, "Simulation_Type"); SimType::Enum sim_type; if (sSimType == "GENERIC_SIM") sim_type = SimType::GENERIC_SIM; #ifndef DISABLE_VECTOR else if (sSimType == "VECTOR_SIM") sim_type = SimType::VECTOR_SIM; #endif #ifndef DISABLE_MALARIA else if (sSimType == "MALARIA_SIM") sim_type = SimType::MALARIA_SIM; #endif #ifdef ENABLE_ENVIRONMENTAL else if (sSimType == "ENVIRONMENTAL_SIM") sim_type = SimType::ENVIRONMENTAL_SIM; #endif #ifdef ENABLE_POLIO else if (sSimType == "POLIO_SIM") sim_type = SimType::POLIO_SIM; #endif #ifdef ENABLE_ENVIRONMENTAL else if (sSimType == "ENVIRONMENTAL_SIM") sim_type = SimType::ENVIRONMENTAL_SIM; #endif #ifdef ENABLE_TYPHOID else if (sSimType == "TYPHOID_SIM") sim_type = SimType::TYPHOID_SIM; #endif #ifndef DISABLE_AIRBORNE else if (sSimType == "AIRBORNE_SIM") sim_type = SimType::AIRBORNE_SIM; #endif #ifndef DISABLE_TBHIV else if (sSimType == "TBHIV_SIM") sim_type = SimType::TBHIV_SIM; #endif // TBHIV #ifndef DISABLE_STI else if (sSimType == "STI_SIM") sim_type = SimType::STI_SIM; #endif #ifndef DISABLE_HIV else if (sSimType == "HIV_SIM") sim_type = SimType::HIV_SIM; #endif // HIV #ifdef ENABLE_DENGUE else if (sSimType == "DENGUE_SIM") sim_type = SimType::DENGUE_SIM; #endif #ifdef ENABLE_PYTHON_FEVER else if (sSimType == "PY_SIM") sim_type = SimType::PY_SIM; #endif else { std::ostringstream msg; msg << "Simulation_Type " << sSimType << " not recognized." << std::endl; throw Kernel::GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, msg.str().c_str() ); } #ifdef _DLLS_ // Look through disease dll directory, do LoadLibrary on each .dll, // do GetProcAddress on GetMimeType() and CreateSimulation typedef ISimulation* (*createSim)(const Environment *); std::map< std::string, createSim > createSimFuncPtrMap; // Note map operator [] will automatically initialize the pointer to NULL if not found DllLoader dllLoader; if (!dllLoader.LoadDiseaseDlls(createSimFuncPtrMap) || !createSimFuncPtrMap[sSimType]) { std::ostringstream msg; msg << "Failed to load disease emodules for SimType: " << SimType::pairs::lookup_key(sim_type) << " from path: " << dllLoader.GetEModulePath(DISEASE_EMODULES).c_str() << std::endl; throw Kernel::DllLoadingException( __FILE__, __LINE__, __FUNCTION__, msg.str().c_str()); return newsim; } newsim = createSimFuncPtrMap[sSimType](EnvPtr); release_assert(newsim); #else // _DLLS_ switch (sim_type) { case SimType::GENERIC_SIM: newsim = Simulation::CreateSimulation(EnvPtr->Config); break; #if defined(ENABLE_ENVIRONMENTAL) case SimType::ENVIRONMENTAL_SIM: newsim = SimulationEnvironmental::CreateSimulation(EnvPtr->Config); break; #endif #if defined( ENABLE_POLIO) case SimType::POLIO_SIM: newsim = SimulationPolio::CreateSimulation(EnvPtr->Config); break; #endif #if defined( ENABLE_TYPHOID) case SimType::TYPHOID_SIM: newsim = SimulationTyphoid::CreateSimulation(EnvPtr->Config); break; #endif #ifndef DISABLE_VECTOR case SimType::VECTOR_SIM: newsim = SimulationVector::CreateSimulation(EnvPtr->Config); break; #endif #ifndef DISABLE_MALARIA case SimType::MALARIA_SIM: newsim = SimulationMalaria::CreateSimulation(EnvPtr->Config); break; #endif #ifndef DISABLE_AIRBORNE case SimType::AIRBORNE_SIM: throw IllegalOperationException( __FILE__, __LINE__, __FUNCTION__, "AIRBORNE_SIM currently disabled. Consider using GENERIC_SIM or TBHIV_SIM." ); newsim = SimulationAirborne::CreateSimulation(EnvPtr->Config); break; #endif #ifndef DISABLE_TBHIV case SimType::TBHIV_SIM: newsim = SimulationTBHIV::CreateSimulation(EnvPtr->Config); break; #endif // TBHIV #ifndef DISABLE_STI case SimType::STI_SIM: newsim = SimulationSTI::CreateSimulation(EnvPtr->Config); break; #endif #ifndef DISABLE_HIV case SimType::HIV_SIM: newsim = SimulationHIV::CreateSimulation(EnvPtr->Config); break; #endif // HIV #ifdef ENABLE_DENGUE case SimType::DENGUE_SIM: newsim = SimulationDengue::CreateSimulation(EnvPtr->Config); break; #endif #ifdef ENABLE_PYTHON_FEVER case SimType::PY_SIM: newsim = SimulationPy::CreateSimulation(EnvPtr->Config); break; #endif default: // Is it even possible to get here anymore? Won't the SimulationConfig error out earlier parsing the parameter-string? //("SimulationFactory::CreateSimulation(): Error, Simulation_Type %d is not implemented.\n", sim_type); //throw BadEnumInSwitchStatementException( __FILE__, __LINE__, __FUNCTION__, "sim_type", sim_type, SimType::pairs::lookup_key( sim_typ )); // JB break; } #endif release_assert(newsim); } catch ( GeneralConfigurationException& e ) { throw e; } return newsim; }
bool ATLAS_IsAvailable() { return atlas_dll.LoadDLL(); }