Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ArchiveBuilder.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "precompiled.h"
19 
20 #include "ArchiveBuilder.h"
21 
24 #include "lib/tex/tex_codec.h"
26 #include "lib/file/vfs/vfs_util.h"
27 #include "ps/XML/Xeromyces.h"
28 
29 // Disable "'boost::algorithm::detail::is_classifiedF' : assignment operator could not be generated"
30 #if MSC_VERSION
31 #pragma warning(disable:4512)
32 #endif
33 
34 #include <boost/algorithm/string.hpp>
35 
36 CArchiveBuilder::CArchiveBuilder(const OsPath& mod, const OsPath& tempdir) :
37  m_TempDir(tempdir)
38 {
40 
41  m_VFS = CreateVfs(20*MiB);
42 
43  DeleteDirectory(m_TempDir/"_archivecache"); // clean up in case the last run failed
44 
45  m_VFS->Mount(L"cache/", m_TempDir/"_archivecache"/"");
46 
47  m_VFS->Mount(L"", mod/"", VFS_MOUNT_MUST_EXIST | VFS_MOUNT_KEEP_DELETED);
48 
49  // Collect the list of files before loading any base mods
50  vfs::ForEachFile(m_VFS, L"", &CollectFileCB, (uintptr_t)static_cast<void*>(this), 0, vfs::DIR_RECURSIVE);
51 }
52 
54 {
55  m_VFS.reset();
56 
57  DeleteDirectory(m_TempDir/"_archivecache");
58 
60 }
61 
63 {
64  m_VFS->Mount(L"", mod/"", VFS_MOUNT_MUST_EXIST);
65 }
66 
67 void CArchiveBuilder::Build(const OsPath& archive, bool compress)
68 {
69  // By default we disable zip compression because it significantly hurts download
70  // size for releases (which re-compress all files with better compression
71  // algorithms) - it's probably most important currently to optimise for
72  // download size rather than install size or startup performance.
73  // (See http://trac.wildfiregames.com/ticket/671)
74  const bool noDeflate = !compress;
75 
76  PIArchiveWriter writer = CreateArchiveWriter_Zip(archive, noDeflate);
77 
78  // Use CTextureManager instead of CTextureConverter directly,
79  // so it can deal with all the loading of settings.xml files
80  CTextureManager textureManager(m_VFS, true, true);
81 
82  CColladaManager colladaManager(m_VFS);
83 
84  CXeromyces xero;
85 
86  for (size_t i = 0; i < m_Files.size(); ++i)
87  {
88  Status ret;
89 
90  const VfsPath path = m_Files[i];
91  OsPath realPath;
92  ret = m_VFS->GetRealPath(path, realPath);
93  ENSURE(ret == INFO::OK);
94 
95  // Compress textures and store the new cached version instead of the original
96  if (boost::algorithm::starts_with(path.string(), L"art/textures/") &&
97  tex_is_known_extension(path) &&
98  // Skip some subdirectories where the engine doesn't use CTextureManager yet:
99  !boost::algorithm::starts_with(path.string(), L"art/textures/cursors/") &&
100  !boost::algorithm::starts_with(path.string(), L"art/textures/terrain/alphamaps/")
101  )
102  {
103  VfsPath cachedPath;
104  debug_printf(L"Converting texture %ls\n", realPath.string().c_str());
105  bool ok = textureManager.GenerateCachedTexture(path, cachedPath);
106  ENSURE(ok);
107 
108  OsPath cachedRealPath;
109  ret = m_VFS->GetRealPath(VfsPath("cache")/cachedPath, cachedRealPath);
110  ENSURE(ret == INFO::OK);
111 
112  writer->AddFile(cachedRealPath, cachedPath);
113 
114  // We don't want to store the original file too (since it's a
115  // large waste of space), so skip to the next file
116  continue;
117  }
118 
119  // Convert DAE models and store the new cached version instead of the original
120  if (path.Extension() == L".dae")
121  {
123 
124  if (boost::algorithm::starts_with(path.string(), L"art/meshes/"))
125  type = CColladaManager::PMD;
126  else if (boost::algorithm::starts_with(path.string(), L"art/animation/"))
127  type = CColladaManager::PSA;
128  else
129  {
130  // Unknown type of DAE, just add to archive and continue
131  writer->AddFile(realPath, path);
132  continue;
133  }
134 
135  VfsPath cachedPath;
136  debug_printf(L"Converting model %ls\n", realPath.string().c_str());
137  bool ok = colladaManager.GenerateCachedFile(path, type, cachedPath);
138 
139  // The DAE might fail to convert for whatever reason, and in that case
140  // it can't be used in the game, so we just exclude it
141  // (alternatively we could throw release blocking errors on useless files)
142  if (ok)
143  {
144  OsPath cachedRealPath;
145  ret = m_VFS->GetRealPath(VfsPath("cache")/cachedPath, cachedRealPath);
146  ENSURE(ret == INFO::OK);
147 
148  writer->AddFile(cachedRealPath, cachedPath);
149  }
150 
151  // We don't want to store the original file too (since it's a
152  // large waste of space), so skip to the next file
153  continue;
154  }
155 
156  debug_printf(L"Adding %ls\n", realPath.string().c_str());
157  writer->AddFile(realPath, path);
158 
159  // Also cache XMB versions of all XML files
160  if (path.Extension() == L".xml")
161  {
162  VfsPath cachedPath;
163  debug_printf(L"Converting XML file %ls\n", realPath.string().c_str());
164  bool ok = xero.GenerateCachedXMB(m_VFS, path, cachedPath);
165  ENSURE(ok);
166 
167  OsPath cachedRealPath;
168  ret = m_VFS->GetRealPath(VfsPath("cache")/cachedPath, cachedRealPath);
169  ENSURE(ret == INFO::OK);
170 
171  writer->AddFile(cachedRealPath, cachedPath);
172  }
173  }
174 }
175 
176 Status CArchiveBuilder::CollectFileCB(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
177 {
178  CArchiveBuilder* self = static_cast<CArchiveBuilder*>((void*)cbData);
179  self->m_Files.push_back(pathname);
180 
181  return INFO::OK;
182 }
PIArchiveWriter CreateArchiveWriter_Zip(const OsPath &archivePathname, bool noDeflate)
Packages a mod&#39;s files into a distributable archive.
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
bool GenerateCachedTexture(const VfsPath &path, VfsPath &outputPath)
Synchronously converts and compresses and saves the texture, and returns the output path (minus a &quot;ca...
Path VfsPath
VFS path of the form &quot;(dir/)*file?&quot;.
Definition: vfs_path.h:40
const Status OK
Definition: status.h:386
bool tex_is_known_extension(const VfsPath &pathname)
Is the file&#39;s extension that of a texture format supported by tex_load?
Definition: tex.cpp:570
std::vector< VfsPath > m_Files
void AddBaseMod(const OsPath &mod)
Add a mod which will be loaded but not archived, to provide files like textures.xml needed for the co...
shared_ptr< IArchiveWriter > PIArchiveWriter
Definition: archive.h:107
return ERR::VFS_DIR_NOT_FOUND if the given real path doesn&#39;t exist.
Definition: vfs.h:60
Texture manager with asynchronous loading and automatic DDS conversion/compression.
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
PIVFS CreateVfs(size_t cacheSize)
create an instance of a Virtual File System.
Definition: vfs.cpp:321
Definition: path.h:75
bool GenerateCachedFile(const VfsPath &sourcePath, FileType type, VfsPath &archiveCachePath)
Converts DAE to archive cached .pmd/psa and outputs the resulting path (used by archive builder) ...
keep the files named &quot;*.DELETED&quot; visible in the VFS directories.
Definition: vfs.h:68
const String & string() const
Definition: path.h:123
void Build(const OsPath &archive, bool compress)
Do all the processing and packing of files into the archive.
static const size_t MiB
Definition: alignment.h:72
bool GenerateCachedXMB(const PIVFS &vfs, const VfsPath &sourcePath, VfsPath &archiveCachePath)
Convert the given XML file into an XMB in the archive cache.
Definition: Xeromyces.cpp:104
i64 Status
Error handling system.
Definition: status.h:171
Status ForEachFile(const PIVFS &fs, const VfsPath &startPath, FileCallback cb, uintptr_t cbData, const wchar_t *pattern, size_t flags)
call back for each file in a directory tree
Definition: vfs_util.cpp:58
Path Extension() const
Definition: path.h:176
static Status CollectFileCB(const VfsPath &pathname, const CFileInfo &fileInfo, const uintptr_t cbData)
CArchiveBuilder(const OsPath &mod, const OsPath &tempdir)
Initialise the archive builder for processing the given mod.
void tex_codec_register_all()
Manually register codecs.
Definition: tex_codec.cpp:134
Status DeleteDirectory(const OsPath &path)
void tex_codec_unregister_all()
remove all codecs that have been registered.
Definition: tex_codec.cpp:56
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
Definition: debug.cpp:142