void RenderState::loadManagedAssembly() { clearLoadedMods(); Interop::ReloadAssembly(); if (Interop::OK()) { setKeyMap(); } }
// //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// // Called once at program shutdown. // void systemShutdown() { pie_ShutdownRadar(); clearLoadedMods(); shutdownEffectsSystem(); wzSceneEnd(nullptr); // Might want to end the "Main menu loop" or "Main game loop". keyMappings.clear(); // free up all the load functions (all the data should already have been freed) resReleaseAll(); if (!multiShutdown()) // ajl. init net stuff { debug(LOG_FATAL, "Unable to multiShutdown() cleanly!"); abort(); } debug(LOG_MAIN, "shutting down audio subsystems"); debug(LOG_MAIN, "shutting down CD audio"); cdAudio_Close(); if (audio_Disabled() == false && !audio_Shutdown()) { debug(LOG_FATAL, "Unable to audio_Shutdown() cleanly!"); abort(); } debug(LOG_MAIN, "shutting down graphics subsystem"); levShutDown(); widgShutDown(); fpathShutdown(); mapShutdown(); debug(LOG_MAIN, "shutting down everything else"); pal_ShutDown(); // currently unused stub frameShutDown(); // close screen / SDL / resources / cursors / trig screenShutDown(); cleanSearchPath(); // clean PHYSFS search paths debug_exit(); // cleanup debug routines PHYSFS_deinit(); // cleanup PHYSFS (If failure, state of PhysFS is undefined, and probably badly screwed up.) // NOTE: Exception handler is cleaned via atexit(ExchndlShutdown); }
/*! * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs * * Priority: * maps > mods > base > base.wz */ bool rebuildSearchPath( searchPathMode mode, bool force ) { static searchPathMode current_mode = mod_clean; static std::string current_current_map; wzSearchPath * curSearchPath = searchPathRegistry; char tmpstr[PATH_MAX] = "\0"; if (mode != current_mode || (current_map != NULL? current_map : "") != current_current_map || force || (use_override_mods && strcmp(override_mod_list, getModList()))) { if (mode != mod_clean) { rebuildSearchPath( mod_clean, false ); } current_mode = mode; current_current_map = current_map != NULL? current_map : ""; // Start at the lowest priority while( curSearchPath->lowerPriority ) curSearchPath = curSearchPath->lowerPriority; switch ( mode ) { case mod_clean: debug(LOG_WZ, "Cleaning up"); clearLoadedMods(); while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Removing [%s] from search path", curSearchPath->path); #endif // DEBUG // Remove maps and mods removeSubdirs( curSearchPath->path, "maps", NULL ); removeSubdirs( curSearchPath->path, "mods/music", NULL ); removeSubdirs( curSearchPath->path, "mods/global", NULL ); removeSubdirs( curSearchPath->path, "mods/campaign", NULL ); removeSubdirs( curSearchPath->path, "mods/multiplay", NULL ); removeSubdirs( curSearchPath->path, "mods/autoload", NULL ); // Remove multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // Remove plain dir PHYSFS_removeFromSearchPath( curSearchPath->path ); // Remove base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // remove video search path as well sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_removeFromSearchPath( tmpstr ); curSearchPath = curSearchPath->higherPriority; } break; case mod_campaign: debug(LOG_WZ, "*** Switching to campaign mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and campaign mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods?override_mods:campaign_mods, true ); if (!PHYSFS_removeFromSearchPath( curSearchPath->path )) { debug(LOG_WZ, "* Failed to remove path %s again", curSearchPath->path); } // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; case mod_multiplay: debug(LOG_WZ, "*** Switching to multiplay mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } // Add the selected map first, for mapmod support if (current_map != NULL) { std::string realPathAndDir = std::string(PHYSFS_getRealDir(current_map)) + current_map; PHYSFS_addToSearchPath(realPathAndDir.c_str(), PHYSFS_APPEND); } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and multiplay mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods?override_mods:multiplay_mods, true ); PHYSFS_removeFromSearchPath( curSearchPath->path ); // Add multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; default: debug(LOG_ERROR, "Can't switch to unknown mods %i", mode); return false; } if (use_override_mods && mode != mod_clean) { if (strcmp(getModList(),override_mod_list)) { debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list); } clearOverrideMods(); current_mode = mod_override; } // User's home dir must be first so we allways see what we write PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir()); PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND ); #ifdef DEBUG printSearchPath(); #endif // DEBUG } else if (use_override_mods) { // override mods are already the same as current mods, so no need to do anything clearOverrideMods(); } return true; }
void RenderState::loadMods() { clearLoadedMods(); DWORD start,elapsed; start = GetTickCount(); if (Interop::OK()) { Interop::Callbacks().LoadModDB(); int modCount = Interop::Callbacks().GetModCount(); for (int i = 0; i < modCount; ++i) { ModData* mdat = Interop::Callbacks().GetModData(i); if (!mdat) { MM_LOG_INFO(format("Null mod data for index {}", i)); continue; } if (mdat->modType != GPUReplacement && mdat->modType != Deletion) { MM_LOG_INFO(format("Unsupported type: {}", mdat->modType)); continue; } NativeModData nModData; nModData.modData = *mdat; if (mdat->modType == Deletion) { int hashCode = NativeModData::hashCode(nModData.modData.refVertCount, nModData.modData.refPrimCount); _managedMods[hashCode] = nModData; // structwise-copy is ok // thats all we need to do for these. continue; } int declSize = mdat->declSizeBytes; char* declData = declSize > 0 ? new char[declSize] : NULL; int vbSize = mdat->primCount * 3 * mdat->vertSizeBytes; char* vbData = NULL; // index buffers not currently supported int ibSize = 0; //mdat->indexCount * mdat->indexElemSizeBytes; char* ibData = NULL; HRESULT hr; hr = _dev->CreateVertexBuffer(vbSize, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &nModData.vb, NULL); if (FAILED(hr)) { MM_LOG_INFO("failed to create vertex buffer"); return; } this->add(nModData.vb); hr = nModData.vb->Lock(0, 0, (void**)&vbData, 0); if (FAILED(hr)) { MM_LOG_INFO("failed to lock vertex buffer"); return; } int ret = Interop::Callbacks().FillModData(i, declData, declSize, vbData, vbSize, ibData, ibSize); hr = nModData.vb->Unlock(); if (FAILED(hr)) { MM_LOG_INFO("failed to unlock vb"); return; } if (ret == 0) { // fill was ok // create vertex declaration _dev->CreateVertexDeclaration((D3DVERTEXELEMENT9*)declData, &nModData.decl); if (nModData.decl) { this->add(nModData.decl); } int hashCode = NativeModData::hashCode(nModData.modData.refVertCount, nModData.modData.refPrimCount); // create textures for (Uint32 i = 0; i < MaxModTextures; ++i) { if (wcslen(nModData.modData.texPath[i]) > 0) { IDirect3DTexture9 * tex = NULL; HRESULT hr = D3DXCreateTextureFromFileW(_dev, nModData.modData.texPath[i], &tex); if (FAILED(hr)) { MM_LOG_INFO(fmt::format("Error: failed to create mod texture for stage {}", i)); } else { //char* mbName = Util::convertToMB(nModData.modData.texPath[i]); //MM_LOG_INFO(fmt::format("Created texture for stage {} from path {}", i, mbName)); //delete[] mbName; nModData.texture[i] = tex; this->add(tex); } } } // store in mod DB _managedMods[hashCode] = nModData; // structwise-copy is ok } delete [] declData; // the docs don't say it, but I'm pretty sure that CreateVertexDeclaration copies this data, so ok to delete } } elapsed = GetTickCount() - start; MM_LOG_INFO(format("Mod Load time (Native+Managed): {}", elapsed)); }
/*! * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs * * Priority: * maps > mods > base > base.wz */ bool rebuildSearchPath(searchPathMode mode, bool force, const char *current_map) { static searchPathMode current_mode = mod_clean; static std::string current_current_map; wzSearchPath *curSearchPath = searchPathRegistry; char tmpstr[PATH_MAX] = "\0"; if (mode != current_mode || (current_map != nullptr ? current_map : "") != current_current_map || force || (use_override_mods && override_mod_list != getModList())) { if (mode != mod_clean) { rebuildSearchPath(mod_clean, false); } current_mode = mode; current_current_map = current_map != nullptr ? current_map : ""; // Start at the lowest priority while (curSearchPath->lowerPriority) { curSearchPath = curSearchPath->lowerPriority; } switch (mode) { case mod_clean: debug(LOG_WZ, "Cleaning up"); clearLoadedMods(); while (curSearchPath) { #ifdef DEBUG debug(LOG_WZ, "Removing [%s] from search path", curSearchPath->path); #endif // DEBUG // Remove maps and mods removeSubdirs(curSearchPath->path, "maps"); removeSubdirs(curSearchPath->path, "mods/music"); removeSubdirs(curSearchPath->path, "mods/global"); removeSubdirs(curSearchPath->path, "mods"); removeSubdirs(curSearchPath->path, "mods/autoload"); removeSubdirs(curSearchPath->path, "mods/campaign"); removeSubdirs(curSearchPath->path, "mods/multiplay"); removeSubdirs(curSearchPath->path, "mods/downloads"); // Remove multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); WZ_PHYSFS_unmount(tmpstr); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); WZ_PHYSFS_unmount(tmpstr); // Remove plain dir WZ_PHYSFS_unmount(curSearchPath->path); // Remove base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); WZ_PHYSFS_unmount(tmpstr); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); WZ_PHYSFS_unmount(tmpstr); // remove video search path as well sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); WZ_PHYSFS_unmount(tmpstr); curSearchPath = curSearchPath->higherPriority; } break; case mod_campaign: debug(LOG_WZ, "*** Switching to campaign mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) { curSearchPath = curSearchPath->lowerPriority; } while (curSearchPath) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and campaign mods PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND); addSubdirs(curSearchPath->path, "mods/music", PHYSFS_APPEND, nullptr, false); addSubdirs(curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true); addSubdirs(curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true); addSubdirs(curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods ? &override_mods : nullptr, true); addSubdirs(curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods ? &override_mods : &campaign_mods, true); if (!WZ_PHYSFS_unmount(curSearchPath->path)) { debug(LOG_WZ, "* Failed to remove path %s again", curSearchPath->path); } // Add plain dir PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } break; case mod_multiplay: debug(LOG_WZ, "*** Switching to multiplay mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } // Add the selected map first, for mapmod support if (current_map != nullptr) { WzString realPathAndDir = WzString::fromUtf8(PHYSFS_getRealDir(current_map)) + current_map; realPathAndDir.replace("/", PHYSFS_getDirSeparator()); // Windows fix PHYSFS_mount(realPathAndDir.toUtf8().c_str(), NULL, PHYSFS_APPEND); } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) { curSearchPath = curSearchPath->lowerPriority; } while (curSearchPath) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and multiplay mods PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND); addSubdirs(curSearchPath->path, "mods/music", PHYSFS_APPEND, nullptr, false); if (NetPlay.isHost || !NetPlay.bComms) { addSubdirs(curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true); addSubdirs(curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true); addSubdirs(curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods ? &override_mods : nullptr, true); addSubdirs(curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods ? &override_mods : &multiplay_mods, true); } else { std::vector<std::string> hashList; for (Sha256 &hash : game.modHashes) { hashList = {hash.toString()}; addSubdirs(curSearchPath->path, "mods/downloads", PHYSFS_APPEND, &hashList, true); } } WZ_PHYSFS_unmount(curSearchPath->path); // Add multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); // Add plain dir PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } break; default: debug(LOG_ERROR, "Can't switch to unknown mods %i", mode); return false; } if (use_override_mods && mode != mod_clean) { if (getModList() != override_mod_list) { debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list.c_str()); } clearOverrideMods(); current_mode = mod_override; } // User's home dir must be first so we always see what we write WZ_PHYSFS_unmount(PHYSFS_getWriteDir()); PHYSFS_mount(PHYSFS_getWriteDir(), NULL, PHYSFS_PREPEND); #ifdef DEBUG printSearchPath(); #endif // DEBUG } else if (use_override_mods) { // override mods are already the same as current mods, so no need to do anything clearOverrideMods(); } return true; }