1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
namespace Agi {
/**
* WagProperty represents a single property from WinAGI's *.wag file.
* A property consists of a header and of data.
* The header consists of the following:
* - Property code (Integer/Enumeration, 1 byte)
* - Property type (Integer/Enumeration, 1 byte)
* - Property number (Integer, 1 byte)
* - Property size (Little endian integer, 2 bytes)
* And then there's the data with as many bytes as defined in the header's property size variable.
*/
class WagProperty {
// Constants, enumerations etc
public:
/**
* Property codes taken from WinAGI 1.1.21's source code file WinAGI/AGIObjects.bas.
*/
enum WagPropertyCode {
PC_GAMEDESC = 129, ///< Game description (WinAGI 1.1.21 limits these to 4096 bytes)
PC_GAMEAUTHOR, ///< Game author (WinAGI 1.1.21 limits these to 256 bytes)
PC_GAMEID, ///< Game ID
PC_INTVERSION, ///< Interpreter version (WinAGI 1.1.21 defaults to version 2.917)
PC_GAMELAST, ///< Last edit date
PC_GAMEVERSION, ///< Game version (WinAGI 1.1.21 limits these to 256 bytes)
PC_GAMEABOUT, ///< About game (WinAGI 1.1.21 limits these to 4096 bytes)
PC_GAMEEXEC, ///< Game executable
PC_RESDIR, ///< Resource directory name
PC_DEFSYNTAX, ///< Default syntax
PC_INVOBJDESC = 144,
PC_VOCABWORDDESC = 160,
PC_PALETTE = 172,
PC_USERESNAMES = 180,
PC_LOGIC = 192,
PC_PICTURE = 208,
PC_SOUND = 224,
PC_VIEW = 240,
PC_UNDEFINED = 0x100 ///< An undefined property code (Added for ScummVM).
};
/**
* Property types taken from WinAGI 1.1.21's source code file WinAGI/AGIObjects.bas.
* At the moment these aren't really at all needed by ScummVM. Just here if anyone decides to use them.
*/
enum WagPropertyType {
PT_ID,
PT_DESC,
PT_SYNTAX,
PT_CRC32,
PT_KEY,
PT_INST0,
PT_INST1,
PT_INST2,
PT_MUTE0,
PT_MUTE1,
PT_MUTE2,
PT_MUTE3,
PT_TPQN,
PT_ROOM,
PT_VIS0,
PT_VIS1,
PT_VIS2,
PT_VIS3,
PT_ALL = 0xff,
PT_UNDEFINED = 0x100 ///< An undefined property type (Added for ScummVM).
};
// Constructors, destructors, operators etc
public:
/**
* Creates an empty WagProperty object.
* No property header or property data in it.
*/
WagProperty();
/**
* Destructor. Releases allocated memory if any etc. The usual.
*/
~WagProperty();
/**
* Copy constructor. Deep copies the variables.
*/
WagProperty(const WagProperty &other);
/**
* Assignment operator. Deep copies the variables.
*/
WagProperty &operator=(const WagProperty &other);
// Non-public helper methods
protected:
/**
* Sets the default values for member variables.
*/
void setDefaults();
/**
* Delete's the property's data from memory if we have it, otherwise does nothing.
*/
void deleteData();
/**
* Deep copies the parameter object to this object.
* @param other The object to be deep copied to this object.
*/
void deepCopy(const WagProperty &other);
// Public methods that have side-effects
public:
/**
* Read in a property (Header and data).
* @return True if reading was a success, false otherwise.
*/
bool read(Common::SeekableReadStream &stream);
/**
* Clears the property.
* After this the property is empty. No header or data.
*/
void clear();
// Public access functions
public:
/**
* Was the property read ok from the source stream?
*/
bool readOk() const { return _readOk; }
/**
* Return the property's code.
* @return The property's code if readOk(), PC_UNDEFINED otherwise.
*/
enum WagPropertyCode getCode() const { return _propCode; }
/**
* Return the property's type.
* @return The property's type if readOk(), PT_UNDEFINED otherwise.
*/
enum WagPropertyType getType() const { return _propType; }
/**
* Return the property's number.
* @return The property's number if readOk(), 0 otherwise.
*/
byte getNumber() const { return _propNum; }
/**
* Return the property's data's length.
* @return The property's data's length if readOk(), 0 otherwise.
*/
uint16 getSize() const { return _propSize; }
/**
* Return property's data. Constant access version.
* Can be used as a C-style string (i.e. this is guaranteed to have a trailing zero).
* @return The property's data if readOk(), NULL otherwise.
*/
const char *getData() const { return _propData; }
// Member variables
protected:
bool _readOk; ///< Was the property read ok from the source stream?
enum WagPropertyCode _propCode; ///< Property code (Part of the property's header)
enum WagPropertyType _propType; ///< Property type (Part of the property's header)
byte _propNum; ///< Property number (Part of the property's header)
uint16 _propSize; ///< Property's size (Part of the property's header)
char *_propData; ///< The property's data (Plus a trailing zero for C-style string access)
};
/**
* Class for parsing *.wag files created by WinAGI.
* Using this class you can get information about fanmade AGI games if they have provided a *.wag file with them.
*/
class WagFileParser {
// Constants, type definitions, enumerations etc.
public:
enum {
WINAGI_VERSION_LENGTH = 16 ///< WinAGI's version string's length (Always 16)
};
typedef Common::Array<WagProperty> PropertyList; ///< A type definition for an array of *.wag file properties
public:
/**
* Constructor. Creates a WagFileParser object in a default state.
*/
WagFileParser();
/**
* Destructor.
*/
~WagFileParser();
/**
* Loads a *.wag file and parses it.
* @note After this you can access the loaded properties using getProperty() and getProperties() etc.
* @param filename Name of the file to be parsed.
* @return True if parsed successfully, false otherwise.
*/
bool parse(const Common::FSNode &node);
/**
* Get list of the loaded properties.
* @note Use only after a call to parse() first.
* @return The list of loaded properties.
*/
const PropertyList &getProperties() const { return _propList; }
/**
* Get property with the given property code.
* @note Use only after a call to parse() first.
* @return Pointer to the property if its found in memory, NULL otherwise.
*
* TODO/FIXME: Handle cases where several properties with the given property code are found.
* At the moment we don't need this functionality because the properties we use
* for fallback detection probably don't have multiples in the WAG-file.
* TODO: Make this faster than linear time if desired/needed.
*/
const WagProperty *getProperty(const WagProperty::WagPropertyCode code) const;
/**
* Tests if the given property contains a valid AGI interpreter version string.
* A valid AGI interpreter version string is of the form "X.Y" or "X,Y" where
* X is a single decimal digit and Y is a string of decimal digits (At least one digit).
* @param version The property to be tested.
* @return True if the given property contains a valid AGI interpreter version string, false otherwise.
*/
bool checkAgiVersionProperty(const WagProperty &version) const;
/**
* Convert property's data to an AGI interpreter version number.
* @param version The property to be converted (Property code should be PC_INTVERSION).
* @return AGI interpreter version number if successful, 0 otherwise.
*/
uint16 convertToAgiVersionNumber(const WagProperty &version);
/**
* Was the file parsed successfully?
* @return True if file was parsed successfully, false otherwise.
*/
bool parsedOk() const { return _parsedOk; }
protected:
/**
* Checks if stream has a valid WinAGI version string in its end.
* @param stream The stream to be checked.
* @return True if reading was successful and stream contains a valid WinAGI version string, false otherwise.
*/
bool checkWagVersion(Common::SeekableReadStream &stream);
/**
* Checks if we're at or past the end of the properties stored in the stream.
* @param stream The stream whose seeking position is to be checked.
* @return True if stream's seeking position is at or past the end of the properties, false otherwise.
*/
bool endOfProperties(const Common::SeekableReadStream &stream) const;
// Member variables
protected:
PropertyList _propList; ///< List of loaded properties from the file.
bool _parsedOk; ///< Did the parsing of the file go ok?
};
} // End of namespace Agi
|