aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devtools/create_xeen/cc.cpp55
-rw-r--r--devtools/create_xeen/cc.h20
-rw-r--r--devtools/create_xeen/clouds.cpp82
-rw-r--r--devtools/create_xeen/clouds.h31
-rw-r--r--devtools/create_xeen/constants.cpp53
-rw-r--r--devtools/create_xeen/create_xeen.cpp6
-rw-r--r--devtools/create_xeen/file.h6
-rw-r--r--devtools/create_xeen/module.mk1
-rw-r--r--engines/xeen/map.cpp28
-rw-r--r--engines/xeen/resources.cpp9
-rw-r--r--engines/xeen/resources.h3
-rw-r--r--engines/xeen/spells.cpp2
-rw-r--r--engines/xeen/xeen.cpp3
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;