1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 //=============================================================================
24 //
25 // Asset manager class for reading and writing game resources.
26 //-----------------------------------------------------------------------------
27 //
28 // The code is based on CLIB32, by Chris Jones (1998-99), DJGPP implementation
29 // of the CLIB reader.
30 //
31 //-----------------------------------------------------------------------------
32 // TODO: consider replace/merge with PhysFS library in the future.
33 //
34 // TODO: support streams that work on a file subsection, limited by size,
35 // to avoid having to return an asset size separately from a stream.
36 // TODO: return stream as smart pointer.
37 //
38 //=============================================================================
39 
40 #ifndef AGS_SHARED_CORE_ASSET_MANAGER_H
41 #define AGS_SHARED_CORE_ASSET_MANAGER_H
42 
43 #include "common/stream.h"
44 #include "ags/lib/std/functional.h"
45 #include "ags/lib/std/memory.h"
46 #include "ags/shared/core/asset.h"
47 #include "ags/shared/util/file.h" // TODO: extract filestream mode constants or introduce generic ones
48 
49 namespace AGS3 {
50 namespace AGS {
51 namespace Shared {
52 
53 class Stream;
54 struct MultiFileLib;
55 
56 enum AssetSearchPriority {
57 	kAssetPriorityDir,
58 	kAssetPriorityLib
59 };
60 
61 enum AssetError {
62 	kAssetNoError = 0,
63 	kAssetErrNoLibFile = -1, // library file not found or can't be read
64 	kAssetErrLibParse = -2, // bad library file format or read error
65 	kAssetErrNoManager = -6, // asset manager not initialized
66 };
67 
68 // Explicit location of asset data
69 struct AssetLocation {
70 	String      FileName;   // file where asset is located
71 	soff_t      Offset;     // asset's position in file (in bytes)
72 	soff_t      Size;       // asset's size (in bytes)
73 
74 	AssetLocation();
75 };
76 
77 
78 class AssetManager {
79 public:
80 	AssetManager();
~AssetManager()81 	~AssetManager() {
82 		RemoveAllLibraries();
83 	}
84 
85 	// Test if given file is main data file
86 	static bool         IsDataFile(const String &data_file);
87 	// Read data file table of contents into provided struct
88 	static AssetError   ReadDataFileTOC(const String &data_file, AssetLibInfo &lib);
89 
90 	// Sets asset search priority (in which order manager will search available locations)
91 	void         SetSearchPriority(AssetSearchPriority priority);
92 	// Gets current asset search priority
93 	AssetSearchPriority GetSearchPriority() const;
94 
95 	// Add library location to the list of asset locations
96 	AssetError   AddLibrary(const String &path, const AssetLibInfo **lib = nullptr);
97 	// Add library location, specifying comma-separated list of filters
98 	AssetError   AddLibrary(const String &path, const String &filters, const AssetLibInfo **lib = nullptr);
99 	// Remove library location from the list of asset locations
100 	void         RemoveLibrary(const String &path);
101 	// Removes all libraries
102 	void         RemoveAllLibraries();
103 
104 	size_t       GetLibraryCount() const;
105 	const AssetLibInfo *GetLibraryInfo(size_t index) const;
106 	// Tells whether asset exists in any of the registered search locations
107 	bool         DoesAssetExist(const String &asset_name, const String &filter = "") const;
108 	// Finds asset only looking for bare files in directories; returns full path or empty string if failed
109 	String       FindAssetFileOnly(const String &asset_name, const String &filter = "") const;
110 	// Open asset stream in the given work mode; returns null if asset is not found or cannot be opened
111 	// This method only searches in libraries that do not have any defined filters
112 	Stream *OpenAsset(const String &asset_name, soff_t *asset_size = nullptr,
113 					  FileOpenMode open_mode = kFile_Open,
114 					  FileWorkMode work_mode = kFile_Read) const;
115 	// Open asset stream, providing a single filter to search in matching libraries
116 	Stream *OpenAsset(const String &asset_name, const String &filter, soff_t *asset_size = nullptr,
117 					  FileOpenMode open_mode = kFile_Open,
118 					  FileWorkMode work_mode = kFile_Read) const;
119 	// Open asset stream in the given work mode; returns null if asset is not found or cannot be opened
120 	// This method only searches in libraries that do not have any defined filters
121 	Common::SeekableReadStream *OpenAssetStream(const String &asset_name) const;
122 	// Open asset stream, providing a single filter to search in matching libraries
123 	Common::SeekableReadStream *OpenAssetStream(const String &asset_name, const String &filter) const;
124 
125 private:
126 	struct AssetLibEx : AssetLibInfo {
127 		std::vector<String> Filters; // asset filters this library is matching to
128 	};
129 
130 	// Loads library and registers its contents into the cache
131 	AssetError  RegisterAssetLib(const String &path, AssetLibEx *&lib);
132 
133 	// Tries to find asset in known locations, tests if it's possible to open, and fills in AssetLocation
134 	bool        GetAsset(const String &asset_name, const String &filter, bool dir_only, AssetLocation *loc, Shared::FileOpenMode open_mode, Shared::FileWorkMode work_mode) const;
135 	bool        GetAssetFromLib(const AssetLibInfo *lib, const String &asset_name, AssetLocation *loc, Shared::FileOpenMode open_mode, Shared::FileWorkMode work_mode) const;
136 	bool        GetAssetFromDir(const AssetLibInfo *lib, const String &asset_name, AssetLocation *loc, Shared::FileOpenMode open_mode, Shared::FileWorkMode work_mode) const;
137 
138 	std::vector<AssetLibEx *> _libs;
139 	std::vector<AssetLibEx *> _activeLibs;
140 
141 	struct LibsByPriority {
142 		AssetSearchPriority Priority = kAssetPriorityDir;
143 
144 		bool operator()(const AssetLibInfo *x, const AssetLibInfo *y) const;
145 	} _libsByPriority;
146 };
147 
148 
149 String GetAssetErrorText(AssetError err);
150 
151 } // namespace Shared
152 } // namespace AGS
153 } // namespace AGS3
154 
155 #endif
156