diff options
-rw-r--r-- | devtools/create_xeen/cc.cpp | 55 | ||||
-rw-r--r-- | devtools/create_xeen/cc.h | 20 | ||||
-rw-r--r-- | devtools/create_xeen/clouds.cpp | 82 | ||||
-rw-r--r-- | devtools/create_xeen/clouds.h | 31 | ||||
-rw-r--r-- | devtools/create_xeen/constants.cpp | 53 | ||||
-rw-r--r-- | devtools/create_xeen/create_xeen.cpp | 6 | ||||
-rw-r--r-- | devtools/create_xeen/file.h | 6 | ||||
-rw-r--r-- | devtools/create_xeen/module.mk | 1 | ||||
-rw-r--r-- | engines/xeen/map.cpp | 28 | ||||
-rw-r--r-- | engines/xeen/resources.cpp | 9 | ||||
-rw-r--r-- | engines/xeen/resources.h | 3 | ||||
-rw-r--r-- | engines/xeen/spells.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/xeen.cpp | 3 |
13 files changed, 222 insertions, 77 deletions
diff --git a/devtools/create_xeen/cc.cpp b/devtools/create_xeen/cc.cpp index 4020301412..14f605ff0c 100644 --- a/devtools/create_xeen/cc.cpp +++ b/devtools/create_xeen/cc.cpp @@ -57,6 +57,33 @@ uint16 CCArchive::convertNameToId(const Common::String &resourceName) { return total; } +void CCArchive::loadIndex() { + int count = _file.readUint16LE(); + + // Read in the data for the archive's index + byte *rawIndex = new byte[count * 8]; + _file.read(rawIndex, count * 8); + + // Decrypt the index + int seed = 0xac; + for (int i = 0; i < count * 8; ++i, seed += 0x67) { + rawIndex[i] = (byte)((((rawIndex[i] << 2) | (rawIndex[i] >> 6)) + seed) & 0xff); + } + + // Extract the index data into entry structures + _index.resize(count); + const byte *entryP = &rawIndex[0]; + for (int idx = 0; idx < count; ++idx, entryP += 8) { + CCEntry &entry = _index[idx]; + entry._id = READ_LE_UINT16(entryP); + entry._offset = READ_LE_UINT32(entryP + 2) & 0xffffff; + entry._size = READ_LE_UINT16(entryP + 5); + assert(!entryP[7]); + } + + delete[] rawIndex; +} + void CCArchive::saveIndex() { // Fill up the data for the index entries into a raw data block byte *rawIndex = new byte[_index.size() * 8]; @@ -107,10 +134,34 @@ void CCArchive::saveEntries() { } void CCArchive::close() { - saveIndex(); - saveEntries(); + if (_mode == kWrite) { + saveIndex(); + saveEntries(); + } } void CCArchive::add(const Common::String &name, Common::MemFile &f) { + assert(_mode == kWrite); _index.push_back(CCEntry(convertNameToId(name), f.getData(), f.size())); } + +Common::MemFile CCArchive::getMember(const Common::String &name) { + uint16 id = convertNameToId(name); + + for (uint idx = 0; idx < _index.size(); ++idx) { + CCEntry &entry = _index[idx]; + if (entry._id == id) { + assert(entry._size < MAX_MEM_SIZE); + _file.seek(entry._offset); + _file.read(entry._data, entry._size); + + // Decrypt the entry + for (int i = 0; i < entry._size; ++i) + entry._data[i] ^= 0x35; + + return Common::MemFile(entry._data, entry._size); + } + } + + error("Failed to find %s", name.c_str()); +}
\ No newline at end of file diff --git a/devtools/create_xeen/cc.h b/devtools/create_xeen/cc.h index 192a7d5c37..47a5112573 100644 --- a/devtools/create_xeen/cc.h +++ b/devtools/create_xeen/cc.h @@ -45,10 +45,13 @@ struct CCEntry { } }; +enum CCAccess { kRead = 0, kWrite = 1 }; + class CCArchive { private: Common::Array<CCEntry> _index; Common::File &_file; + CCAccess _mode; private: /** * Convert a resource name to it's equivalent hash key @@ -56,6 +59,11 @@ private: uint16 convertNameToId(const Common::String &resourceName); /** + * Loads an index from the file + */ + void loadIndex(); + + /** * Saves the index to the file */ void saveIndex(); @@ -68,10 +76,13 @@ public: /** * Constructor */ - CCArchive(Common::File &file) : _file(file) {} + CCArchive(Common::File &file, CCAccess mode) : _file(file), _mode(mode) { + if (mode == kRead) + loadIndex(); + } /** - * Finishes the CC file, writing out the resulting content + * In write mode, finishes the CC file, writing out the resulting content */ void close(); @@ -79,6 +90,11 @@ public: * Adds an entry to the CC */ void add(const Common::String &name, Common::MemFile &f); + + /** + * In read mode, gets a member + */ + Common::MemFile getMember(const Common::String &name); }; #endif diff --git a/devtools/create_xeen/clouds.cpp b/devtools/create_xeen/clouds.cpp new file mode 100644 index 0000000000..2e41263bde --- /dev/null +++ b/devtools/create_xeen/clouds.cpp @@ -0,0 +1,82 @@ +/* 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. + * + */ + + // Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +// HACK to allow building with the SDL backend on MinGW +// see bug #1800764 "TOOLS: MinGW tools building broken" +#ifdef main +#undef main +#endif // main + +#include "file.h" +#include "clouds.h" + +static const char *const MAP_NAMES[86] = { + "", "Area A1", "Area A2", "Area A3", "Area A4", "Area B1", "Area B2", + "Area B3", "Area B4", "Area C1", "Area C2", "Area C3", "Area C4", + "Area D1", "Area D2", "Area D3", "Area D4", "Area E1", "Area E2", + "Area E3", "Area E4", "Area F1", "Area F2", "Area F3", "Area F4", + "Witch Clouds", "High Magic Clouds", "Clouds of Xeen", "Vertigo", + "Nightshadow", "Rivercity", "Asp", "Winterkill", "Dwarf Mine 1", + "Dwarf Mine 2", "Dwarf Mine 3", "Dwarf Mine 4", "Dwarf Mine 5", + "Deep Mine Alpha", "Deep Mine Theta", "Deep Mine Kappa", + "Deep Mine Omega", "Cave of Illusion Level 1", "Cave of Illusion Level 2", + "Cave of Illusion Level 3", "Cave of Illusion Level 4", + "Volcano Cave Level 1", "Volcano Cave Level 2", "Volcano Cave Level 3", + "Shangri-La", "Dragon Cave", "Witch Tower Level 1", "Witch Tower Level 2", + "Witch Tower Level 3", "Witch Tower Level 4", "Tower of High Magic Level 1", + "Tower of High Magic Level 2", "Tower of High Magic Level 3", + "Tower of High Magic Level 4", "Darzog's Tower Level 1", + "Darzog's Tower Level 2", "Darzog's Tower Level 3", "Darzog's Tower Level 4", + "Burlock Dungeon", "Castle Burlock Level 1", "Castle Burlock Level 2", + "Castle Burlock Level 3", "Basenji Dungeon", "Castle Basenji Level 1", + "Castle Basenji Level 2", "Castle Basenji Level 3", "Newcastle Dungeon", + "Newcastle Foundation", "Newcastle Level 1", "Newcastle Level 2", + "Xeen's Castle Level 1", "Xeen's Castle Level 2", "Xeen's Castle Level 3", + "Xeen's Castle Level 4", "Ancient Temple of Yak", "Tomb of a 1000 Terrors", + "Golem Dungeon", "Sphinx Body", "Sphinx Head", "Sphinx Dungeon", + "The Warzone" +}; + +void writeCloudsData(CCArchive &cc, const char *darkName) { + Common::File darkFile; + if (darkFile.open(darkName, Common::kFileReadMode)) { + CCArchive darkCc(darkFile, kRead); + + cc.add("mae.cld", darkCc.getMember("mae.xen")); + cc.add("spells.cld", darkCc.getMember("spells.xen")); + cc.add("animinfo.cld", darkCc.getMember("clouds.dat")); + cc.add("monsters.cld", darkCc.getMember("xeen.mon")); + cc.add("wallpics.cld", darkCc.getMember("xeenpic.dat")); + + Common::MemFile mapNames; + for (int idx = 0; idx < 86; ++idx) + mapNames.syncString(MAP_NAMES[idx]); + cc.add("mapnames.cld", mapNames); + + darkFile.close(); + } else { + printf("Could not find %s to get Clouds data\n", darkName); + } +} diff --git a/devtools/create_xeen/clouds.h b/devtools/create_xeen/clouds.h new file mode 100644 index 0000000000..4c077186d2 --- /dev/null +++ b/devtools/create_xeen/clouds.h @@ -0,0 +1,31 @@ +/* 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. + * + */ + +#ifndef CLOUDS_H +#define CLOUDS_H + +#include "common/scummsys.h" +#include "cc.h" + +extern void writeCloudsData(CCArchive &cc, const char *darkName); + +#endif diff --git a/devtools/create_xeen/constants.cpp b/devtools/create_xeen/constants.cpp index 3df02dff50..1ab1a7a50a 100644 --- a/devtools/create_xeen/constants.cpp +++ b/devtools/create_xeen/constants.cpp @@ -1767,49 +1767,6 @@ const char *const MUSIC_FILES2[6][7] = { { "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m", "sf05.m" } }; -const char *const SPELL_NAMES[77] = { - "Acid Spray", "Awaken", "Beast Master", "Bless", "Clairvoyance", "Cold Ray", - "Create Food", "Cure Disease", "Cure Paralysis", "Cure Poison", "Cure Wounds", - "Dancing Sword", "Day of Protection", "Day of Sorcery", "Deadly Swarm", - "Detect Monster", "Divine Intervention", "Dragon Sleep", "Elemental Storm", - "Enchant Item", "Energy Blast", "Etherealize", "Fantastic Freeze", "Fiery Flail", - "Finger of Death", "Fire Ball", "First Aid", "Flying Fist", "Frost Bite", - "Golem Stopper", "Heroism", "Holy Bonus", "Holy Word", "Hypnotize", - "Identify Monster", "Implosion", "Incinerate", "Inferno", "Insect Spray", - "Item to Gold", "Jump", "Levitate", "Light", "Lightning Bolt", "Lloyd's Beacon", - "Magic Arrow", "Mass Distortion", "Mega Volts", "Moon Ray", "Nature's Cure", - "Pain", "Poison Volley", "Power Cure", "Power Shield", "Prismatic Light", - "Prot. from Elements", "Raise Dead", "Recharge Item", "Resurrect", "Revitalize", - "Shrapmetal", "Sleep", "Sparks", "Star Burst", "Stone to Flesh", "Sun Ray", - "Super Shelter", "Suppress Disease", "Suppress Poison", "Teleport", - "Time Distortion", "Town Portal", "Toxic Cloud", "Turn Undead", "Walk on Water", - "Wizard Eye", "None Ready" -}; - -const char *const MAE_NAMES[131] = { - "", "burning ", "fiery ", "pyric ", "fuming ", "flaming ", "seething ", - "blazing ", "scorching ", "flickering ", "sparking ", "static ", - "flashing ", "shocking ", "electric ", "dyna ", "icy ", "frost ", - "freezing ", "cold ", "cryo ", "acidic ", "venemous ", "poisonous ", - "toxic ", "noxious ", "glowing ", "incandescent ", "dense ", "sonic ", - "power ", "thermal ", "radiating ", "kinetic ", "mystic ", "magical ", - "ectoplasmic ", "wooden ", "leather ", "brass ", "bronze ", "iron ", - "silver ", "steel ", "gold ", "platinum ", "glass ", "coral ", "crystal ", - "lapis ", "pearl ", "amber ", "ebony ", "quartz ", "ruby ", "emerald ", - "sapphire ", "diamond ", "obsidian ", "might ", "strength ", "warrior ", - "ogre ", "giant ", "thunder ", "force ", "power ", "dragon ", "photon ", - "clever ", "mind ", "sage ", "thought ", "knowledge ", "intellect ", - "wisdom ", "genius ", "buddy ", "friendship ", "charm ", "personality ", - "charisma ", "leadership ", "ego ", "holy ", "quick ", "swift ", "fast ", - "rapid ", "speed ", "wind ", "accelerator ", "velocity ", "sharp ", - "accurate ", "marksman ", "precision ", "true ", "exacto ", "clover ", - "chance ", "winners ", "lucky ", "gamblers ", "leprechauns ", "vigor ", - "health ", "life ", "troll ", "vampiric ", "spell ", "castors ", "witch ", - "mage ", "archmage ", "arcane ", "protection ", "armored ", "defender ", - "stealth ", "divine ", "mugger ", "burgler ", "looter ", "brigand ", - "filch ", "thief ", "rogue ", "plunder ", "criminal ", "pirate " -}; - void writeConstants(CCArchive &cc) { Common::MemFile file; file.syncString(CREDITS); @@ -2138,14 +2095,4 @@ void writeConstants(CCArchive &cc) { file.syncStrings2D((const char *const *)MUSIC_FILES2, 6, 7); cc.add("CONSTANTS", file); - - // Fallback spell names list needed for Clouds of Xeen - Common::MemFile spells; - spells.syncStrings(SPELL_NAMES, 77); - cc.add("spells.xen", spells); - - // Fallback MAE names list needed for Clouds of Xeen - Common::MemFile mae; - mae.syncStrings(MAE_NAMES, 131); - cc.add("mae.xen", mae); } diff --git a/devtools/create_xeen/create_xeen.cpp b/devtools/create_xeen/create_xeen.cpp index 92c7a3bcf6..5b66870be4 100644 --- a/devtools/create_xeen/create_xeen.cpp +++ b/devtools/create_xeen/create_xeen.cpp @@ -34,6 +34,7 @@ #include <string.h> #include "cc.h" #include "file.h" +#include "clouds.h" #include "constants.h" #include "map.h" @@ -57,11 +58,14 @@ int main(int argc, char *argv[]) { error("Could not open input file"); } - CCArchive cc(outputFile); + CCArchive cc(outputFile, kWrite); writeVersion(cc); writeConstants(cc); writeMap(cc); + const char *darkName = argc > 2 ? argv[2] : "dark.cc"; + writeCloudsData(cc, darkName); + cc.close(); return 0; } diff --git a/devtools/create_xeen/file.h b/devtools/create_xeen/file.h index 7ea5acfb4a..15091bcd11 100644 --- a/devtools/create_xeen/file.h +++ b/devtools/create_xeen/file.h @@ -118,8 +118,7 @@ public: void writeString(const char *msg) { if (!msg) { writeByte(0); - } - else { + } else { do { writeByte(*msg); } while (*msg++); @@ -179,6 +178,9 @@ public: MemFile() : _size(0), _offset(0) { memset(_data, 0, MAX_MEM_SIZE); } + MemFile(const byte *data, size_t size) : _size(size), _offset(0) { + memcpy(_data, data, size); + } virtual ~MemFile() {} bool open() { diff --git a/devtools/create_xeen/module.mk b/devtools/create_xeen/module.mk index e325d6e9b8..29f2f3027f 100644 --- a/devtools/create_xeen/module.mk +++ b/devtools/create_xeen/module.mk @@ -3,6 +3,7 @@ MODULE := devtools/create_xeen MODULE_OBJS := \ create_xeen.o \ cc.o \ + clouds.o \ constants.o \ hashmap.o \ map.o \ diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index abe91e57d3..2200d145ef 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -655,9 +655,9 @@ void Map::load(int mapId) { _monsterData.load("dark.mon"); _wallPicSprites.load("darkpic.dat"); } else if (_vm->getGameID() == GType_Clouds) { - _animationInfo.load("clouds.dat"); - _monsterData.load("xeen.mon"); - _wallPicSprites.load("xeenpic.dat"); + _animationInfo.load("animinfo.cld"); + _monsterData.load("monsters.cld"); + _wallPicSprites.load("wallpics.cld"); } else if (_vm->getGameID() == GType_WorldOfXeen) { files.setGameCc(1); @@ -747,15 +747,19 @@ void Map::load(int mapId) { if (!textLoaded) { textLoaded = true; - Common::String txtName = Common::String::format("%s%c%03d.txt", - isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId); - File fText(txtName, 1); - char mazeName[33]; - fText.read(mazeName, 33); - mazeName[32] = '\0'; - - _mazeName = Common::String(mazeName); - fText.close(); + if (g_vm->getGameID() == GType_Clouds) { + _mazeName = Res._cloudsMapNames[mapId]; + } else { + Common::String txtName = Common::String::format("%s%c%03d.txt", + isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId); + File fText(txtName, 1); + char mazeName[33]; + fText.read(mazeName, 33); + mazeName[32] = '\0'; + + _mazeName = Common::String(mazeName); + fText.close(); + } // Load the monster/object data Common::String mobName = Common::String::format("maze%c%03d.mob", diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 632cf3ddfe..bed8a1a9b7 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -36,11 +36,18 @@ Resources::Resources() { _globalSprites.load("global.icn"); - File f("mae.xen"); + File f((g_vm->getGameID() == GType_Clouds) ? "mae.cld" : "mae.xen"); while (f.pos() < f.size()) _maeNames.push_back(f.readString()); f.close(); + if (g_vm->getGameID() == GType_Clouds) { + f.open("mapnames.cld"); + while (f.pos() < f.size()) + _cloudsMapNames.push_back(f.readString()); + f.close(); + } + // Set up items array to map to the names of items in each category ITEM_NAMES[CATEGORY_WEAPON] = &WEAPON_NAMES[0]; ITEM_NAMES[CATEGORY_ARMOR] = &ARMOR_NAMES[0]; diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 8cdeaf4c21..2761f401fc 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -110,7 +110,8 @@ private: void loadData(); public: SpriteResource _globalSprites; - Common::StringArray _maeNames; // Magic and equipment names + Common::StringArray _maeNames; // Magic and equipment names + Common::StringArray _cloudsMapNames; // Clouds of Xeen map names const char **ITEM_NAMES[4]; // Data loaded from xeen.ccs diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 53303c384b..72140a2d2f 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -36,7 +36,7 @@ Spells::Spells(XeenEngine *vm) : _vm(vm) { } void Spells::load() { - File f1("spells.xen", 1); + File f1((g_vm->getGameID() == GType_Clouds) ? "spells.cld" : "spells.xen", 1); while (f1.pos() < f1.size()) _spellNames.push_back(f1.readString()); f1.close(); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 39fc773d39..9acf2c51b4 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -167,8 +167,7 @@ void XeenEngine::play() { _screen->loadBackground("back.raw"); _screen->loadPalette("mm4.pal"); - if (getGameID() != GType_WorldOfXeen && getGameID() != GType_Swords - && !_map->_loadDarkSide) { + if (getGameID() == GType_DarkSide && !_map->_loadDarkSide) { _map->_loadDarkSide = true; _party->_mazeId = 29; _party->_mazeDirection = DIR_NORTH; |