Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "cc.h"
#include "common/endian.h"
uint16 CCArchive::convertNameToId(const Common::String &resourceName) {
if (resourceName.empty())
return 0xffff;
Common::String name = resourceName;
name.toUppercase();
// Check if a resource number is being directly specified
if (name.size() == 4) {
char *endPtr;
uint16 num = (uint16)strtol(name.c_str(), &endPtr, 16);
if (!*endPtr)
return num;
}
const byte *msgP = (const byte *)name.c_str();
int total = *msgP++;
for (; *msgP; total += *msgP++) {
// Rotate the bits in 'total' right 7 places
total = (total & 0x007F) << 9 | (total & 0xFF80) >> 7;
}
return total;
}
void CCArchive::loadIndex() {
int count = _file.readUint16LE();
long size = count * 8;
// Read in the data for the archive's index
byte *rawIndex = new byte[size];
if (_file.read(rawIndex, size) != size) {
delete[] rawIndex;
error("Failed to read %ld bytes from CC archive", size);
}
// 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::close() {
}
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) {
if (_file.seek(entry._offset) != 0)
error("Failed to seek to %d for CC archive", entry._offset);
if (_file.read(entry._data, entry._size) != entry._size)
error("Failed to read %hu bytes from CC archive", 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());
}

View File

@@ -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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CC_H
#define CC_H
#include "file.h"
#include "common/array.h"
#include "common/str.h"
/**
* Details of a single entry in a CC file index
*/
struct CCEntry {
uint16 _id;
int _offset;
uint16 _size;
byte _data[MAX_MEM_SIZE];
CCEntry() : _id(0), _offset(0), _size(0) {
memset(_data, 0, MAX_MEM_SIZE);
}
CCEntry(uint16 id, const byte *data, uint32 size) :
_id(id), _offset(0), _size(size) {
memcpy(_data, data, size);
}
};
class CCArchive {
private:
Common::Array<CCEntry> _index;
Common::File &_file;
private:
/**
* Convert a resource name to it's equivalent hash key
*/
uint16 convertNameToId(const Common::String &resourceName);
/**
* Loads an index from the file
*/
void loadIndex();
public:
/**
* Constructor
*/
CCArchive(Common::File &file) : _file(file) {
loadIndex();
}
~CCArchive() {
_file.close();
}
void close();
/**
* Gets a member
*/
Common::MemFile getMember(const Common::String &name);
};
#endif

View File

@@ -0,0 +1,84 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "clouds.h"
#include "cc.h"
#include "file.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(const char *darkName) {
Common::File darkFile;
if (darkFile.open(darkName, Common::kFileReadMode)) {
CCArchive darkCc(darkFile);
Common::MemFile mae = darkCc.getMember("mae.xen");
Common::MemFile spells = darkCc.getMember("spells.xen");
Common::MemFile animInfo = darkCc.getMember("clouds.dat");
Common::MemFile monsters = darkCc.getMember("xeen.mon");
Common::MemFile wallPics = darkCc.getMember("xeenpic.dat");
Common::MemFile mirror = darkCc.getMember("xeenmirr.txt");
Common::File::write("mae.cld", mae);
Common::File::write("spells.cld", spells);
Common::File::write("animinfo.cld", animInfo);
Common::File::write("monsters.cld", monsters);
Common::File::write("wallpics.cld", wallPics);
Common::File::write("xeenmirr.txt", mirror);
Common::MemFile mapNames;
for (int idx = 0; idx < 86; ++idx)
mapNames.syncString(MAP_NAMES[idx]);
Common::File::write("mapnames.cld", mapNames);
darkFile.close();
} else {
error("Could not find %s to get Clouds data", darkName);
}
}

View File

@@ -0,0 +1,27 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CLOUDS_H
#define CLOUDS_H
extern void writeCloudsData(const char *darkName);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,623 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include "common/scummsys.h"
#include "cc.h"
enum MagicSpell {
MS_AcidSpray = 0,
MS_Awaken = 1,
MS_BeastMaster = 2,
MS_Bless = 3,
MS_Clairvoyance = 4,
MS_ColdRay = 5,
MS_CreateFood = 6,
MS_CureDisease = 7,
MS_CureParalysis = 8,
MS_CurePoison = 9,
MS_CureWounds = 10,
MS_DancingSword = 11,
MS_DayOfProtection = 12,
MS_DayOfSorcery = 13,
MS_DeadlySwarm = 14,
MS_DetectMonster = 15,
MS_DivineIntervention = 16,
MS_DragonSleep = 17,
MS_ElementalStorm = 18,
MS_EnchantItem = 19,
MS_EnergyBlast = 20,
MS_Etheralize = 21,
MS_FantasticFreeze = 22,
MS_FieryFlail = 23,
MS_FingerOfDeath = 24,
MS_Fireball = 25,
MS_FirstAid = 26,
MS_FlyingFist = 27,
MS_FrostBite = 28,
MS_GolemStopper = 29,
MS_Heroism = 30,
MS_HolyBonus = 31,
MS_HolyWord = 32,
MS_Hynotize = 33,
MS_IdentifyMonster = 34,
MS_Implosion = 35,
MS_Incinerate = 36,
MS_Inferno = 37,
MS_InsectSpray = 38,
MS_ItemToGold = 39,
MS_Jump = 40,
MS_Levitate = 41,
MS_Light = 42,
MS_LightningBolt = 43,
MS_LloydsBeacon = 44,
MS_MagicArrow = 45,
MS_MassDistortion = 46,
MS_MegaVolts = 47,
MS_MoonRay = 48,
MS_NaturesCure = 49,
MS_Pain = 50,
MS_PoisonVolley = 51,
MS_PowerCure = 52,
MS_PowerShield = 53,
MS_PrismaticLight = 54,
MS_ProtFromElements = 55,
MS_RaiseDead = 56,
MS_RechargeItem = 57,
MS_Resurrection = 58,
MS_Revitalize = 59,
MS_Shrapmetal = 60,
MS_Sleep = 61,
MS_Sparks = 62,
MS_StarBurst = 63,
MS_StoneToFlesh = 64,
MS_SunRay = 65,
MS_SuperShelter = 66,
MS_SuppressDisease = 67,
MS_SuppressPoison = 68,
MS_Teleport = 69,
MS_TimeDistortion = 70,
MS_TownPortal = 71,
MS_ToxicCloud = 72,
MS_TurnUndead = 73,
MS_WalkOnWater = 74,
MS_WizardEye = 75,
NO_SPELL = 76
};
class LangConstants {
public:
static const char *const TERRAIN_TYPES[6];
static const char *const OUTDOORS_WALL_TYPES[16];
static const char *const SURFACE_NAMES[16];
static const byte SYMBOLS[20][64];
static const byte TEXT_COLORS[40][4];
static const byte TEXT_COLORS_STARTUP[40][4];
static const int RACE_HP_BONUSES[5];
static const int RACE_SP_BONUSES[5][2];
static const int CLASS_EXP_LEVELS[10];
static const int CONDITION_COLORS[17];
static const int FACE_CONDITION_FRAMES[17];
static const int CHAR_FACES_X[6];
static const int HP_BARS_X[6];
static const byte DARKNESS_XLAT[3][256];
static const int SCREEN_POSITIONING_X[4][48];
static const int SCREEN_POSITIONING_Y[4][48];
static const int MONSTER_GRID_BITMASK[12];
static const int INDOOR_OBJECT_X[2][12];
static const int MAP_OBJECT_Y[2][12];
static const int INDOOR_MONSTERS_Y[4];
static const int OUTDOOR_OBJECT_X[2][12];
static const int OUTDOOR_MONSTER_INDEXES[26];
static const int OUTDOOR_MONSTERS_Y[26];
static const int DIRECTION_ANIM_POSITIONS[4][4];
static const byte WALL_SHIFTS[4][48];
static const int DRAW_NUMBERS[25];
static const int DRAW_FRAMES[25][2];
static const int COMBAT_FLOAT_X[8];
static const int COMBAT_FLOAT_Y[8];
static const int MONSTER_EFFECT_FLAGS[15][8];
static const int SPELLS_ALLOWED[3][40];
static const int BASE_HP_BY_CLASS[10];
static const int AGE_RANGES[10];
static const int AGE_RANGES_ADJUST[2][10];
static const int STAT_VALUES[24];
static const int STAT_BONUSES[24];
static const int ELEMENTAL_CATEGORIES[6];
static const int ATTRIBUTE_CATEGORIES[10];
static const int ATTRIBUTE_BONUSES[72];
static const int ELEMENTAL_RESISTENCES[37];
static const int ELEMENTAL_DAMAGE[37];
static const int WEAPON_DAMAGE_BASE[35];
static const int WEAPON_DAMAGE_MULTIPLIER[35];
static const int METAL_DAMAGE[22];
static const int METAL_DAMAGE_PERCENT[22];
static const int METAL_LAC[22];
static const int ARMOR_STRENGTHS[14];
static const int MAKE_ITEM_ARR1[6];
static const int MAKE_ITEM_ARR2[6][7][2];
static const int MAKE_ITEM_ARR3[10][7][2];
static const int MAKE_ITEM_ARR4[2][7][2];
static const int MAKE_ITEM_ARR5[8][2];
static const int OUTDOOR_DRAWSTRUCT_INDEXES[44];
static const int TOWN_MAXES[2][11];
static const char *const TOWN_ACTION_MUSIC[2][7];
static const char *const TOWN_ACTION_SHAPES[7];
static const int TOWN_ACTION_FILES[2][7];
static const int TAVERN_EXIT_LIST[2][6][5][2];
static const int MISC_SPELL_INDEX[74];
static const int SPELL_COSTS[77];
static const int DARK_SPELL_RANGES[12][2];
static const int SWORDS_SPELL_RANGES[12][2];
static const int CLOUDS_GUILD_SPELLS[5][20];
static const int DARK_SPELL_OFFSETS[3][39];
static const int SPELL_GEM_COST[77];
static const int BLACKSMITH_MAP_IDS[2][4];
static const int WEAPON_BASE_COSTS[35];
static const int ARMOR_BASE_COSTS[14];
static const int ACCESSORY_BASE_COSTS[11];
static const int MISC_MATERIAL_COSTS[22];
static const int MISC_BASE_COSTS[76];
static const int METAL_BASE_MULTIPLIERS[22];
static const int ITEM_SKILL_DIVISORS[4];
static const int RESTRICTION_OFFSETS[4];
static const int ITEM_RESTRICTIONS[86];
static const int NEW_CHAR_SKILLS[10];
static const int NEW_CHAR_SKILLS_LEN[10];
static const int NEW_CHAR_RACE_SKILLS[10];
static const int RACE_MAGIC_RESISTENCES[5];
static const int RACE_FIRE_RESISTENCES[5];
static const int RACE_ELECTRIC_RESISTENCES[5];
static const int RACE_COLD_RESISTENCES[5];
static const int RACE_ENERGY_RESISTENCES[5];
static const int RACE_POISON_RESISTENCES[5];
static const int NEW_CHARACTER_SPELLS[10][4];
static const int TOWN_MAP_NUMBERS[3][5];
static const char *const EVENT_SAMPLES[6];
static const char *const MUSIC_FILES1[5];
static const char *const MUSIC_FILES2[6][7];
virtual ~LangConstants() {}
virtual const char *CLOUDS_CREDITS() = 0;
virtual const char *DARK_SIDE_CREDITS() = 0;
virtual const char *SWORDS_CREDITS1() = 0;
virtual const char *SWORDS_CREDITS2() = 0;
virtual const char *OPTIONS_MENU() = 0;
virtual const char **GAME_NAMES() = 0;
virtual const char *THE_PARTY_NEEDS_REST() = 0;
virtual const char *WHO_WILL() = 0;
virtual const char *HOW_MUCH() = 0;
virtual const char *WHATS_THE_PASSWORD() = 0;
virtual const char *PASSWORD_INCORRECT() = 0;
virtual const char *IN_NO_CONDITION() = 0;
virtual const char *NOTHING_HERE() = 0;
virtual const char **WHO_ACTIONS() = 0;
virtual const char **WHO_WILL_ACTIONS() = 0;
virtual const char **DIRECTION_TEXT_UPPER() = 0;
virtual const char **DIRECTION_TEXT() = 0;
virtual const char **RACE_NAMES() = 0;
virtual const char **ALIGNMENT_NAMES() = 0;
virtual const char **SEX_NAMES() = 0;
virtual const char **SKILL_NAMES() = 0;
virtual const char **CLASS_NAMES() = 0;
virtual const char **CONDITION_NAMES_M() = 0;
virtual const char **CONDITION_NAMES_F() = 0;
virtual const char *GOOD() = 0;
virtual const char *BLESSED() = 0;
virtual const char *POWER_SHIELD() = 0;
virtual const char *HOLY_BONUS() = 0;
virtual const char *HEROISM() = 0;
virtual const char *IN_PARTY() = 0;
virtual const char *PARTY_DETAILS() = 0;
virtual const char *PARTY_DIALOG_TEXT() = 0;
virtual const char *NO_ONE_TO_ADVENTURE_WITH() = 0;
virtual const char *YOUR_ROSTER_IS_FULL() = 0;
virtual const char *PLEASE_WAIT() = 0;
virtual const char *OOPS() = 0;
virtual const char *BANK_TEXT() = 0;
virtual const char *BLACKSMITH_TEXT() = 0;
virtual const char *GUILD_NOT_MEMBER_TEXT() = 0;
virtual const char *GUILD_TEXT() = 0;
virtual const char *TAVERN_TEXT() = 0;
virtual const char *FOOD_AND_DRINK() = 0;
virtual const char *GOOD_STUFF() = 0;
virtual const char *HAVE_A_DRINK() = 0;
virtual const char *YOURE_DRUNK() = 0;
virtual const char *TEMPLE_TEXT() = 0;
virtual const char *EXPERIENCE_FOR_LEVEL() = 0;
virtual const char *TRAINING_LEARNED_ALL() = 0;
virtual const char *ELIGIBLE_FOR_LEVEL() = 0;
virtual const char *TRAINING_TEXT() = 0;
virtual const char *GOLD_GEMS() = 0;
virtual const char *GOLD_GEMS_2() = 0;
virtual const char **DEPOSIT_WITHDRAWL() = 0;
virtual const char *NOT_ENOUGH_X_IN_THE_Y() = 0;
virtual const char *NO_X_IN_THE_Y() = 0;
virtual const char **STAT_NAMES() = 0;
virtual const char **CONSUMABLE_NAMES() = 0;
virtual const char **CONSUMABLE_GOLD_FORMS() = 0;
virtual const char **CONSUMABLE_GEM_FORMS() = 0;
virtual const char **WHERE_NAMES() = 0;
virtual const char *AMOUNT() = 0;
virtual const char *FOOD_PACKS_FULL() = 0;
virtual const char *BUY_SPELLS() = 0;
virtual const char *GUILD_OPTIONS() = 0;
virtual const char *NOT_A_SPELL_CASTER() = 0;
virtual const char *SPELLS_LEARNED_ALL() = 0;
virtual const char *SPELLS_FOR() = 0;
virtual const char *SPELL_LINES_0_TO_9() = 0;
virtual const char *SPELLS_DIALOG_SPELLS() = 0;
virtual const char *SPELL_PTS() = 0;
virtual const char *GOLD() = 0;
virtual const char *SPELL_INFO() = 0;
virtual const char *SPELL_PURCHASE() = 0;
virtual const char *MAP_TEXT() = 0;
virtual const char *LIGHT_COUNT_TEXT() = 0;
virtual const char *FIRE_RESISTENCE_TEXT() = 0;
virtual const char *ELECRICITY_RESISTENCE_TEXT() = 0;
virtual const char *COLD_RESISTENCE_TEXT() = 0;
virtual const char *POISON_RESISTENCE_TEXT() = 0;
virtual const char *CLAIRVOYANCE_TEXT() = 0;
virtual const char *LEVITATE_TEXT() = 0;
virtual const char *WALK_ON_WATER_TEXT() = 0;
virtual const char *GAME_INFORMATION() = 0;
virtual const char *WORLD_GAME_TEXT() = 0;
virtual const char *DARKSIDE_GAME_TEXT() = 0;
virtual const char *CLOUDS_GAME_TEXT() = 0;
virtual const char *SWORDS_GAME_TEXT() = 0;
virtual const char **WEEK_DAY_STRINGS() = 0;
virtual const char *CHARACTER_DETAILS() = 0;
virtual const char **DAYS() = 0;
virtual const char *PARTY_GOLD() = 0;
virtual const char *PLUS_14() = 0;
virtual const char *CHARACTER_TEMPLATE() = 0;
virtual const char *EXCHANGING_IN_COMBAT() = 0;
virtual const char *CURRENT_MAXIMUM_RATING_TEXT() = 0;
virtual const char *CURRENT_MAXIMUM_TEXT() = 0;
virtual const char **RATING_TEXT() = 0;
virtual const char **BORN() = 0;
virtual const char *AGE_TEXT() = 0;
virtual const char *LEVEL_TEXT() = 0;
virtual const char *RESISTENCES_TEXT() = 0;
virtual const char *NONE() = 0;
virtual const char *EXPERIENCE_TEXT() = 0;
virtual const char *ELIGIBLE() = 0;
virtual const char *IN_PARTY_IN_BANK() = 0;
virtual const char **FOOD_ON_HAND() = 0;
virtual const char *FOOD_TEXT() = 0;
virtual const char *EXCHANGE_WITH_WHOM() = 0;
virtual const char *QUICK_REF_LINE() = 0;
virtual const char *QUICK_REFERENCE() = 0;
virtual const char *ITEMS_DIALOG_TEXT1() = 0;
virtual const char *ITEMS_DIALOG_TEXT2() = 0;
virtual const char *ITEMS_DIALOG_LINE1() = 0;
virtual const char *ITEMS_DIALOG_LINE2() = 0;
virtual const char *BTN_BUY() = 0;
virtual const char *BTN_SELL() = 0;
virtual const char *BTN_IDENTIFY() = 0;
virtual const char *BTN_FIX() = 0;
virtual const char *BTN_USE() = 0;
virtual const char *BTN_EQUIP() = 0;
virtual const char *BTN_REMOVE() = 0;
virtual const char *BTN_DISCARD() = 0;
virtual const char *BTN_QUEST() = 0;
virtual const char *BTN_ENCHANT() = 0;
virtual const char *BTN_RECHARGE() = 0;
virtual const char *BTN_GOLD() = 0;
virtual const char *ITEM_BROKEN() = 0;
virtual const char *ITEM_CURSED() = 0;
virtual const char *ITEM_OF() = 0;
virtual const char **BONUS_NAMES() = 0;
virtual const char **WEAPON_NAMES() = 0;
virtual const char **ARMOR_NAMES() = 0;
virtual const char **ACCESSORY_NAMES() = 0;
virtual const char **MISC_NAMES() = 0;
virtual const char **SPECIAL_NAMES() = 0;
virtual const char **ELEMENTAL_NAMES() = 0;
virtual const char **ATTRIBUTE_NAMES() = 0;
virtual const char **EFFECTIVENESS_NAMES() = 0;
virtual const char **QUEST_ITEM_NAMES() = 0;
virtual const char **QUEST_ITEM_NAMES_SWORDS() = 0;
virtual const char *NOT_PROFICIENT() = 0;
virtual const char *NO_ITEMS_AVAILABLE() = 0;
virtual const char **CATEGORY_NAMES() = 0;
virtual const char *X_FOR_THE_Y() = 0;
virtual const char *X_FOR_Y() = 0;
virtual const char *X_FOR_Y_GOLD() = 0;
virtual const char *FMT_CHARGES() = 0;
virtual const char *AVAILABLE_GOLD_COST() = 0;
virtual const char *CHARGES() = 0;
virtual const char *COST() = 0;
virtual const char **ITEM_ACTIONS() = 0;
virtual const char *WHICH_ITEM() = 0;
virtual const char *WHATS_YOUR_HURRY() = 0;
virtual const char *USE_ITEM_IN_COMBAT() = 0;
virtual const char *NO_SPECIAL_ABILITIES() = 0;
virtual const char *CANT_CAST_WHILE_ENGAGED() = 0;
virtual const char *EQUIPPED_ALL_YOU_CAN() = 0;
virtual const char *REMOVE_X_TO_EQUIP_Y() = 0;
virtual const char *RING() = 0;
virtual const char *MEDAL() = 0;
virtual const char *CANNOT_REMOVE_CURSED_ITEM() = 0;
virtual const char *CANNOT_DISCARD_CURSED_ITEM() = 0;
virtual const char *PERMANENTLY_DISCARD() = 0;
virtual const char *BACKPACK_IS_FULL() = 0;
virtual const char **CATEGORY_BACKPACK_IS_FULL() = 0;
virtual const char *BUY_X_FOR_Y_GOLD() = 0;
virtual const char *SELL_X_FOR_Y_GOLD() = 0;
virtual const char **GOLDS() = 0;
virtual const char *NO_NEED_OF_THIS() = 0;
virtual const char *NOT_RECHARGABLE() = 0;
virtual const char *NOT_ENCHANTABLE() = 0;
virtual const char *SPELL_FAILED() = 0;
virtual const char *ITEM_NOT_BROKEN() = 0;
virtual const char **FIX_IDENTIFY() = 0;
virtual const char *FIX_IDENTIFY_GOLD() = 0;
virtual const char *IDENTIFY_ITEM_MSG() = 0;
virtual const char *ITEM_DETAILS() = 0;
virtual const char *ALL() = 0;
virtual const char *FIELD_NONE() = 0;
virtual const char *DAMAGE_X_TO_Y() = 0;
virtual const char *ELEMENTAL_XY_DAMAGE() = 0;
virtual const char *ATTR_XY_BONUS() = 0;
virtual const char *EFFECTIVE_AGAINST() = 0;
virtual const char *QUESTS_DIALOG_TEXT() = 0;
virtual const char *CLOUDS_OF_XEEN_LINE() = 0;
virtual const char *DARKSIDE_OF_XEEN_LINE() = 0;
virtual const char *SWORDS_OF_XEEN_LINE() = 0;
virtual const char *NO_QUEST_ITEMS() = 0;
virtual const char *NO_CURRENT_QUESTS() = 0;
virtual const char *NO_AUTO_NOTES() = 0;
virtual const char *QUEST_ITEMS_DATA() = 0;
virtual const char *CURRENT_QUESTS_DATA() = 0;
virtual const char *AUTO_NOTES_DATA() = 0;
virtual const char *REST_COMPLETE() = 0;
virtual const char *PARTY_IS_STARVING() = 0;
virtual const char *HIT_SPELL_POINTS_RESTORED() = 0;
virtual const char *TOO_DANGEROUS_TO_REST() = 0;
virtual const char *SOME_CHARS_MAY_DIE() = 0;
virtual const char *DISMISS_WHOM() = 0;
virtual const char *CANT_DISMISS_LAST_CHAR() = 0;
virtual const char *DELETE_CHAR_WITH_ELDER_WEAPON() = 0;
virtual const char **REMOVE_DELETE() = 0;
virtual const char *REMOVE_OR_DELETE_WHICH() = 0;
virtual const char *YOUR_PARTY_IS_FULL() = 0;
virtual const char *HAS_SLAYER_SWORD() = 0;
virtual const char *SURE_TO_DELETE_CHAR() = 0;
virtual const char *CREATE_CHAR_DETAILS() = 0;
virtual const char *NEW_CHAR_STATS() = 0;
virtual const char *NAME_FOR_NEW_CHARACTER() = 0;
virtual const char *SELECT_CLASS_BEFORE_SAVING() = 0;
virtual const char *EXCHANGE_ATTR_WITH() = 0;
virtual const int *NEW_CHAR_SKILLS_OFFSET() = 0;
virtual const char *COMBAT_DETAILS() = 0;
virtual const char *NOT_ENOUGH_TO_CAST() = 0;
virtual const char **SPELL_CAST_COMPONENTS() = 0;
virtual const char *CAST_SPELL_DETAILS() = 0;
virtual const char *PARTY_FOUND() = 0;
virtual const char *BACKPACKS_FULL_PRESS_KEY() = 0;
virtual const char *HIT_A_KEY() = 0;
virtual const char *GIVE_TREASURE_FORMATTING() = 0;
virtual const char **FOUND() = 0;
virtual const char *X_FOUND_Y() = 0;
virtual const char *ON_WHO() = 0;
virtual const char *WHICH_ELEMENT1() = 0;
virtual const char *WHICH_ELEMENT2() = 0;
virtual const char *DETECT_MONSTERS() = 0;
virtual const char *LLOYDS_BEACON() = 0;
virtual const char *HOW_MANY_SQUARES() = 0;
virtual const char *TOWN_PORTAL() = 0;
virtual const char *TOWN_PORTAL_SWORDS() = 0;
virtual const char *MONSTER_DETAILS() = 0;
virtual const char **MONSTER_SPECIAL_ATTACKS() = 0;
virtual const char *IDENTIFY_MONSTERS() = 0;
virtual const char *MOONS_NOT_ALIGNED() = 0;
virtual const char *AWARDS_FOR() = 0;
virtual const char *AWARDS_TEXT() = 0;
virtual const char *NO_AWARDS() = 0;
virtual const char *WARZONE_BATTLE_MASTER() = 0;
virtual const char *WARZONE_MAXED() = 0;
virtual const char *WARZONE_LEVEL() = 0;
virtual const char *WARZONE_HOW_MANY() = 0;
virtual const char *PICKS_THE_LOCK() = 0;
virtual const char **PICK_FORM() = 0;
virtual const char *UNABLE_TO_PICK_LOCK() = 0;
virtual const char **UNABLE_TO_PICK_FORM() = 0;
virtual const char *CONTROL_PANEL_TEXT() = 0;
virtual const char *CONTROL_PANEL_BUTTONS() = 0;
virtual const char *ON() = 0;
virtual const char *OFF() = 0;
virtual const char *CONFIRM_QUIT() = 0;
virtual const char *MR_WIZARD() = 0;
virtual const char *NO_LOADING_IN_COMBAT() = 0;
virtual const char *NO_SAVING_IN_COMBAT() = 0;
virtual const char *QUICK_FIGHT_TEXT() = 0;
virtual const char **QUICK_FIGHT_OPTIONS() = 0;
virtual const char **WORLD_END_TEXT() = 0;
virtual const char *WORLD_CONGRATULATIONS() = 0;
virtual const char *WORLD_CONGRATULATIONS2() = 0;
virtual const char *CLOUDS_CONGRATULATIONS1() = 0;
virtual const char *CLOUDS_CONGRATULATIONS2() = 0;
virtual const char **GOOBER() = 0;
virtual const char *DIFFICULTY_TEXT() = 0;
virtual const char *SAVE_OFF_LIMITS() = 0;
virtual const char *CLOUDS_INTRO1() = 0;
virtual const char *DARKSIDE_ENDING1() = 0;
virtual const char *DARKSIDE_ENDING2() = 0;
virtual const char *PHAROAH_ENDING_TEXT1() = 0;
virtual const char *PHAROAH_ENDING_TEXT2() = 0;
virtual const char **CLOUDS_MAE_NAMES() = 0;
virtual const char **CLOUDS_MIRROR_LOCATIONS() = 0;
virtual const char **CLOUDS_MAP_NAMES() = 0;
virtual const char **CLOUDS_MONSTERS() = 0;
virtual const char **CLOUDS_SPELLS() = 0;
void writeConstants(Common::String num);
class KeyConstants {
public:
class DialogsCharInfo {
public:
virtual int KEY_ITEM() = 0;
virtual int KEY_QUICK() = 0;
virtual int KEY_EXCHANGE() = 0;
virtual ~DialogsCharInfo() {}
};
virtual DialogsCharInfo *dialogsCharInfo() = 0;
class DialogsControlPanel {
public:
virtual int KEY_FXON() = 0;
virtual int KEY_MUSICON() = 0;
virtual int KEY_LOAD() = 0;
virtual int KEY_SAVE() = 0;
virtual int KEY_QUIT() = 0;
virtual int KEY_MRWIZARD() = 0;
virtual ~DialogsControlPanel() {}
};
virtual DialogsControlPanel *dialogsControlPanel() = 0;
class DialogsCreateChar {
public:
virtual int KEY_ROLL() = 0;
virtual int KEY_CREATE() = 0;
virtual int KEY_MGT() = 0;
virtual int KEY_INT() = 0;
virtual int KEY_PER() = 0;
virtual int KEY_END() = 0;
virtual int KEY_SPD() = 0;
virtual int KEY_ACY() = 0;
virtual int KEY_LCK() = 0;
virtual ~DialogsCreateChar() {}
};
virtual DialogsCreateChar *dialogsCreateChar() = 0;
class DialogsDifficulty {
public:
virtual int KEY_ADVENTURER() = 0;
virtual int KEY_WARRIOR() = 0;
virtual ~DialogsDifficulty() {}
};
virtual DialogsDifficulty *dialogsDifficulty() = 0;
class DialogsItems {
public:
virtual int KEY_WEAPONS() = 0;
virtual int KEY_ARMOR() = 0;
virtual int KEY_ACCESSORY() = 0;
virtual int KEY_MISC() = 0;
virtual int KEY_ENCHANT() = 0;
virtual int KEY_USE() = 0;
virtual int KEY_BUY() = 0;
virtual int KEY_SELL() = 0;
virtual int KEY_IDENTIFY() = 0;
virtual int KEY_FIX() = 0;
virtual int KEY_EQUIP() = 0;
virtual int KEY_REM() = 0;
virtual int KEY_DISC() = 0;
virtual int KEY_QUEST() = 0;
virtual int KEY_RECHRG() = 0;
virtual int KEY_GOLD() = 0;
virtual ~DialogsItems() {}
};
virtual DialogsItems *dialogsItems() = 0;
class DialogsParty {
public:
virtual int KEY_DELETE() = 0;
virtual int KEY_REMOVE() = 0;
virtual int KEY_CREATE() = 0;
virtual int KEY_EXIT() = 0;
virtual ~DialogsParty() {}
};
virtual DialogsParty *dialogsParty() = 0;
class DialogsQuests {
public:
virtual int KEY_QUEST_ITEMS() = 0;
virtual int KEY_CURRENT_QUESTS() = 0;
virtual int KEY_AUTO_NOTES() = 0;
virtual ~DialogsQuests() {}
};
virtual DialogsQuests *dialogsQuests() = 0;
class DialogsQuickFight {
public:
virtual int KEY_NEXT() = 0;
virtual ~DialogsQuickFight() {}
};
virtual DialogsQuickFight *dialogsQuickFight() = 0;
class DialogsSpells {
public:
virtual int KEY_CAST() = 0;
virtual int KEY_NEW() = 0;
virtual int KEY_FIRE() = 0;
virtual int KEY_ELEC() = 0;
virtual int KEY_COLD() = 0;
virtual int KEY_ACID() = 0;
virtual int KEY_SET() = 0;
virtual int KEY_RETURN() = 0;
virtual ~DialogsSpells() {}
};
virtual DialogsSpells *dialogsSpells() = 0;
class Locations {
public:
virtual int KEY_DEP() = 0;
virtual int KEY_WITH() = 0;
virtual int KEY_GOLD() = 0;
virtual int KEY_GEMS() = 0;
virtual int KEY_BROWSE() = 0;
virtual int KEY_BUY_SPELLS() = 0;
virtual int KEY_SPELL_INFO() = 0;
virtual int KEY_SIGN_IN() = 0;
virtual int KEY_DRINK() = 0;
virtual int KEY_FOOD() = 0;
virtual int KEY_TIP() = 0;
virtual int KEY_RUMORS() = 0;
virtual int KEY_HEAL() = 0;
virtual int KEY_DONATION() = 0;
virtual int KEY_UNCURSE() = 0;
virtual int KEY_TRAIN() = 0;
virtual ~Locations() {}
};
virtual Locations *locations() = 0;
class CloudsOfXeenMenu {
public:
virtual int KEY_START_NEW_GAME() = 0;
virtual int KEY_LOAD_GAME() = 0;
virtual int KEY_SHOW_CREDITS() = 0;
virtual int KEY_VIEW_ENDGAME() = 0;
virtual ~CloudsOfXeenMenu() {}
};
virtual CloudsOfXeenMenu *cloudsOfXeenMenu() = 0;
virtual ~KeyConstants() {}
};
virtual KeyConstants *keyConstants() = 0;
};
extern void writeConstants();
#endif

View File

@@ -0,0 +1,78 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cc.h"
#include "file.h"
#include "clouds.h"
#include "swords.h"
#include "constants.h"
#include "map.h"
void NORETURN_PRE error(const char *s, ...) {
va_list ap;
va_start(ap, s);
vfprintf(stderr, s, ap);
va_end(ap);
fputc('\n', stderr);
exit(1);
}
static void writeVersion() {
Common::File f;
if (!f.open("version.txt", Common::kFileWriteMode))
error("Could not create version.txt");
f.write("1.1\n", 4);
f.close();
}
/**
* Creates the different files in the xeen/ subfolder of
* the files/ folder. The files folder overall is zipped
* up to form the xeen data file
*/
int main(int argc, char *argv[]) {
if (argc != 3) {
error("Format: %s dark.cc \"swords xeen.dat\"", argv[0]);
}
writeVersion();
writeConstants();
writeMap();
const char *darkName = argv[1];
writeCloudsData(darkName);
const char *swordsDatName = argv[2];
writeSwordsData(swordsDatName);
printf("File creation done");
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,303 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __FILE_H__
#define __FILE_H__
#include <stdio.h>
#include <stdlib.h>
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
#include "common/endian.h"
#include "common/util.h"
namespace Common {
#define MAX_MEM_SIZE 65536
#define BUFFER_SIZE 16384
enum AccessMode {
kFileReadMode = 1,
kFileWriteMode = 2
};
class Stream {
public:
Stream() {}
virtual ~Stream() {}
virtual int seek(int offset, int whence = SEEK_SET) = 0;
virtual long read(void *buffer, size_t len) = 0;
virtual void write(const void *buffer, size_t len) = 0;
virtual uint pos() const = 0;
virtual uint size() const = 0;
virtual bool eof() const = 0;
void skip(int offset) {
seek(offset, SEEK_CUR);
}
void write(Stream &src, size_t len) {
for (size_t idx = 0; idx < len; ++idx)
writeByte(src.readByte());
}
byte readByte() {
byte v;
read(&v, sizeof(byte));
return v;
}
uint16 readWord() {
uint16 v;
read(&v, sizeof(uint16));
return FROM_LE_16(v);
}
uint readLong() {
uint v;
read(&v, sizeof(uint));
return FROM_LE_32(v);
}
uint readUint16BE() {
uint16 v;
read(&v, sizeof(uint16));
return FROM_BE_16(v);
}
uint readUint16LE() {
uint16 v;
read(&v, sizeof(uint16));
return FROM_LE_16(v);
}
uint readUint32BE() {
uint32 v;
read(&v, sizeof(uint32));
return FROM_BE_32(v);
}
uint readUint32LE() {
uint32 v;
read(&v, sizeof(uint32));
return FROM_LE_32(v);
}
void writeByte(byte v) {
write(&v, sizeof(byte));
}
void writeShort(int8 v) {
write(&v, sizeof(int8));
}
void writeByte(byte v, int len) {
byte *b = new byte[len];
memset(b, v, len);
write(b, len);
delete[] b;
}
void writeWord(uint16 v) {
uint16 vTemp = TO_LE_16(v);
write(&vTemp, sizeof(uint16));
}
void writeLong(uint v) {
uint vTemp = TO_LE_32(v);
write(&vTemp, sizeof(uint));
}
void writeString(const char *msg) {
if (!msg) {
writeByte(0);
} else {
do {
writeByte(*msg);
} while (*msg++);
}
}
};
class MemFile : public Stream {
private:
byte *_data;
size_t _size, _offset;
public:
MemFile() : _size(0), _offset(0) {
_data = new byte[MAX_MEM_SIZE];
memset(_data, 0, MAX_MEM_SIZE);
}
MemFile(const byte *data, size_t size) : _size(size), _offset(0) {
assert(size <= MAX_MEM_SIZE);
_data = new byte[MAX_MEM_SIZE];
memcpy(_data, data, size);
memset(_data + size, 0, MAX_MEM_SIZE - size);
}
virtual ~MemFile() {
delete[] _data;
}
bool open() {
memset(_data, 0, MAX_MEM_SIZE);
_size = _offset = 0;
return true;
}
void close() {
}
virtual int seek(int offset, int whence = SEEK_SET) {
switch (whence) {
default:
// fallthrough intended
case SEEK_SET: _offset = whence; break;
case SEEK_CUR: _offset += whence; break;
case SEEK_END: _offset = _size + whence; break;
}
return _offset;
}
virtual long read(void *buffer, size_t len) {
len = MIN(len, _size - _offset);
memcpy(buffer, &_data[_offset], len);
_offset += len;
return len;
}
virtual void write(const void *buffer, size_t len) {
assert(len <= (MAX_MEM_SIZE - _offset));
memcpy(&_data[_offset], buffer, len);
_offset += len;
_size = MAX(_offset, _size);
}
virtual uint pos() const {
return _offset;
}
virtual uint size() const {
return _size;
}
virtual bool eof() const {
return _offset >= _size;
}
const byte *getData() const {
return _data;
}
void syncString(const char *str) {
write(str, strlen(str) + 1);
}
void syncStrings(const char *const *str, int count) {
writeLong(MKTAG(count, 0, 0, 0));
for (int idx = 0; idx < count; ++idx, ++str)
writeString(*str);
}
void syncStrings2D(const char *const *str, int count1, int count2) {
writeLong(MKTAG(count1, count2, 0, 0));
for (int idx = 0; idx < count1 * count2; ++idx, ++str)
writeString(*str);
}
void syncNumber(const int val) {
writeLong(val);
}
void syncNumbers(const int *vals, int count) {
writeLong(MKTAG(count, 0, 0, 0));
for (int idx = 0; idx < count; ++idx, ++vals)
writeLong(*vals);
}
void syncNumbers2D(const int *vals, int count1, int count2) {
writeLong(MKTAG(count1, count2, 0, 0));
for (int idx = 0; idx < count1 * count2; ++idx, ++vals)
writeLong(*vals);
}
void syncNumbers3D(const int *vals, int count1, int count2, int count3) {
writeLong(MKTAG(count1, count2, count3, 0));
for (int idx = 0; idx < count1 * count2 * count3; ++idx, ++vals)
writeLong(*vals);
}
void syncNumbers4D(const int *vals, int count1, int count2, int count3, int count4) {
writeLong(MKTAG(count1, count2, count3, count4));
for (int idx = 0; idx < count1 * count2 * count3 * count4; ++idx, ++vals)
writeLong(*vals);
}
void syncBytes2D(const byte *vals, int count1, int count2) {
writeLong(MKTAG(count1, count2, 0, 0));
write(vals, count1 * count2);
}
};
class File : public Stream {
private:
::FILE *_f;
public:
File() : _f(nullptr) {}
virtual ~File() { close(); }
bool open(const char *filename, AccessMode mode = kFileReadMode) {
if (mode == kFileReadMode) {
_f = fopen(filename, "rb");
} else {
char fname[256];
sprintf(fname, "../files/xeen/%s", filename);
_f = fopen(fname, "wb+");
}
return (_f != NULL);
}
void close() {
if (_f)
fclose(_f);
_f = nullptr;
}
virtual int seek(int offset, int whence = SEEK_SET) {
return fseek(_f, offset, whence);
}
virtual long read(void *buffer, size_t len) {
return fread(buffer, 1, len, _f);
}
virtual void write(const void *buffer, size_t len) {
assert(_f);
fwrite(buffer, 1, len, _f);
}
virtual uint pos() const {
return ftell(_f);
}
virtual uint size() const {
uint currentPos = pos();
fseek(_f, 0, SEEK_END);
uint result = pos();
fseek(_f, currentPos, SEEK_SET);
return result;
}
virtual bool eof() const {
return feof(_f) != 0;
}
static void write(const char *fname, MemFile &src) {
File f;
if (!f.open(fname, kFileWriteMode)) {
printf("Could not open %s for writing", fname);
exit(1);
}
src.seek(0);
char buffer[BUFFER_SIZE];
size_t count = 0;
while ((count = src.read(buffer, BUFFER_SIZE)) != 0) {
f.write(buffer, count);
}
}
};
} // End of namespace Common
#endif

View File

@@ -0,0 +1,85 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef COMMON_HASH_STR_H
#define COMMON_HASH_STR_H
#include "hashmap.h"
#include "str.h"
namespace Common {
uint hashit(const char *str);
uint hashit_lower(const char *str); // Generate a hash based on the lowercase version of the string
inline uint hashit(const String &str) { return hashit(str.c_str()); }
inline uint hashit_lower(const String &str) { return hashit_lower(str.c_str()); }
// FIXME: The following functors obviously are not consistently named
struct CaseSensitiveString_EqualTo {
bool operator()(const String& x, const String& y) const { return x.equals(y); }
};
struct CaseSensitiveString_Hash {
uint operator()(const String& x) const { return hashit(x.c_str()); }
};
struct IgnoreCase_EqualTo {
bool operator()(const String& x, const String& y) const { return x.equalsIgnoreCase(y); }
};
struct IgnoreCase_Hash {
uint operator()(const String& x) const { return hashit_lower(x.c_str()); }
};
// Specalization of the Hash functor for String objects.
// We do case sensitve hashing here, because that is what
// the default EqualTo is compatible with. If one wants to use
// case insensitve hashing, then only because one wants to use
// IgnoreCase_EqualTo, and then one has to specify a custom
// hash anyway.
template<>
struct Hash<String> {
uint operator()(const String& s) const {
return hashit(s.c_str());
}
};
template<>
struct Hash<const char *> {
uint operator()(const char *s) const {
return hashit(s);
}
};
// String map -- by default case insensitive
typedef HashMap<String, String, IgnoreCase_Hash, IgnoreCase_EqualTo> StringMap;
} // End of namespace Common
#endif

View File

@@ -0,0 +1,108 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
// The hash map (associative array) implementation in this file is
// based on the PyDict implementation of CPython. The erase() method
// is based on example code in the Wikipedia article on Hash tables.
#include "common/hashmap.h"
namespace Common {
// Hash function for strings, taken from CPython.
uint hashit(const char *p) {
uint hash = *p << 7;
byte c;
int size = 0;
while ((c = *p++)) {
hash = (1000003 * hash) ^ c;
size++;
}
return hash ^ size;
}
// Like hashit, but converts every char to lowercase before hashing.
uint hashit_lower(const char *p) {
uint hash = tolower(*p) << 7;
byte c;
int size = 0;
while ((c = *p++)) {
hash = (1000003 * hash) ^ tolower(c);
size++;
}
return hash ^ size;
}
#ifdef DEBUG_HASH_COLLISIONS
static double
g_collisions = 0,
g_dummyHits = 0,
g_lookups = 0,
g_collPerLook = 0,
g_capacity = 0,
g_size = 0;
static int g_max_capacity = 0, g_max_size = 0;
static int g_totalHashmaps = 0;
static int g_stats[4] = {0,0,0,0};
void updateHashCollisionStats(int collisions, int dummyHits, int lookups, int arrsize, int nele) {
g_collisions += collisions;
g_lookups += lookups;
g_dummyHits += dummyHits;
if (lookups)
g_collPerLook += (double)collisions / (double)lookups;
g_capacity += arrsize;
g_size += nele;
g_totalHashmaps++;
if (3*nele <= 2*8)
g_stats[0]++;
if (3*nele <= 2*16)
g_stats[1]++;
if (3*nele <= 2*32)
g_stats[2]++;
if (3*nele <= 2*64)
g_stats[3]++;
g_max_capacity = MAX(g_max_capacity, arrsize);
g_max_size = MAX(g_max_size, nele);
debug("%d hashmaps: colls %.1f; dummies hit %.1f, lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)",
g_totalHashmaps,
g_collisions / g_totalHashmaps,
g_dummyHits / g_totalHashmaps,
g_lookups / g_totalHashmaps,
100 * g_collPerLook / g_totalHashmaps,
g_size / g_totalHashmaps, g_max_size,
g_capacity / g_totalHashmaps, g_max_capacity);
debug(" %d less than %d; %d less than %d; %d less than %d; %d less than %d",
g_stats[0], 2*8/3,
g_stats[1],2*16/3,
g_stats[2],2*32/3,
g_stats[3],2*64/3);
// TODO:
// * Should record the maximal size of the map during its lifetime, not that at its death
// * Should do some statistics: how many maps are less than 2/3*8, 2/3*16, 2/3*32, ...
}
#endif
} // End of namespace Common

View File

@@ -0,0 +1,626 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
// The hash map (associative array) implementation in this file is
// based on the PyDict implementation of CPython.
#ifndef COMMON_HASHMAP_H
#define COMMON_HASHMAP_H
/**
* @def DEBUG_HASH_COLLISIONS
* Enable the following #define if you want to check how many collisions the
* code produces (many collisions indicate either a bad hash function, or a
* hash table that is too small).
*/
//#define DEBUG_HASH_COLLISIONS
/**
* @def USE_HASHMAP_MEMORY_POOL
* Enable the following define to let HashMaps use a memory pool for the
nodes they contain. * This increases memory usage, but also can improve
speed quite a bit.
*/
#define USE_HASHMAP_MEMORY_POOL
#include "common/func.h"
#ifdef DEBUG_HASH_COLLISIONS
#include "common/debug.h"
#endif
#ifdef USE_HASHMAP_MEMORY_POOL
#include "memorypool.h"
#endif
namespace Common {
// The Intel C++ Compiler has difficulties with nested templates.
#if defined(__INTEL_COMPILER)
template<class T> class IteratorImpl;
#endif
/**
* HashMap<Key,Val> maps objects of type Key to objects of type Val.
* For each used Key type, we need an "size_type hashit(Key,size_type)" function
* that computes a hash for the given Key object and returns it as an
* an integer from 0 to hashsize-1, and also an "equality functor".
* that returns true if its two arguments are to be considered
* equal. Also, we assume that "=" works on Val objects for assignment.
*
* If aa is an HashMap<Key,Val>, then space is allocated each time aa[key] is
* referenced, for a new key. If the object is const, then an assertion is
* triggered instead. Hence if you are not sure whether a key is contained in
* the map, use contains() first to check for its presence.
*/
template<class Key, class Val, class HashFunc = Hash<Key>, class EqualFunc = EqualTo<Key> >
class HashMap {
public:
typedef uint size_type;
private:
typedef HashMap<Key, Val, HashFunc, EqualFunc> HM_t;
struct Node {
const Key _key;
Val _value;
explicit Node(const Key &key) : _key(key), _value() {}
Node() : _key(), _value() {}
};
enum {
HASHMAP_PERTURB_SHIFT = 5,
HASHMAP_MIN_CAPACITY = 16,
// The quotient of the next two constants controls how much the
// internal storage of the hashmap may fill up before being
// increased automatically.
// Note: the quotient of these two must be between and different
// from 0 and 1.
HASHMAP_LOADFACTOR_NUMERATOR = 2,
HASHMAP_LOADFACTOR_DENOMINATOR = 3,
HASHMAP_MEMORYPOOL_SIZE = HASHMAP_MIN_CAPACITY * HASHMAP_LOADFACTOR_NUMERATOR / HASHMAP_LOADFACTOR_DENOMINATOR
};
#ifdef USE_HASHMAP_MEMORY_POOL
ObjectPool<Node, HASHMAP_MEMORYPOOL_SIZE> _nodePool;
#endif
Node **_storage; ///< hashtable of size arrsize.
size_type _mask; ///< Capacity of the HashMap minus one; must be a power of two of minus one
size_type _size;
size_type _deleted; ///< Number of deleted elements (_dummyNodes)
HashFunc _hash;
EqualFunc _equal;
/** Default value, returned by the const getVal. */
const Val _defaultVal;
/** Dummy node, used as marker for erased objects. */
#define HASHMAP_DUMMY_NODE ((Node *)1)
#ifdef DEBUG_HASH_COLLISIONS
mutable int _collisions, _lookups, _dummyHits;
#endif
Node *allocNode(const Key &key) {
#ifdef USE_HASHMAP_MEMORY_POOL
return new (_nodePool) Node(key);
#else
return new Node(key);
#endif
}
void freeNode(Node *node) {
if (node && node != HASHMAP_DUMMY_NODE)
#ifdef USE_HASHMAP_MEMORY_POOL
_nodePool.deleteChunk(node);
#else
delete node;
#endif
}
void assign(const HM_t &map);
size_type lookup(const Key &key) const;
size_type lookupAndCreateIfMissing(const Key &key);
void expandStorage(size_type newCapacity);
template<class T> friend class IteratorImpl;
/**
* Simple HashMap iterator implementation.
*/
template<class NodeType>
class IteratorImpl {
friend class HashMap;
#if defined(__INTEL_COMPILER)
template<class T> friend class Common::IteratorImpl;
#else
template<class T> friend class IteratorImpl;
#endif
protected:
typedef const HashMap hashmap_t;
size_type _idx;
hashmap_t *_hashmap;
protected:
IteratorImpl(size_type idx, hashmap_t *hashmap) : _idx(idx), _hashmap(hashmap) {}
NodeType *deref() const {
assert(_hashmap != 0);
assert(_idx <= _hashmap->_mask);
Node *node = _hashmap->_storage[_idx];
assert(node != 0);
assert(node != HASHMAP_DUMMY_NODE);
return node;
}
public:
IteratorImpl() : _idx(0), _hashmap(0) {}
template<class T>
IteratorImpl(const IteratorImpl<T> &c) : _idx(c._idx), _hashmap(c._hashmap) {}
NodeType &operator*() const { return *deref(); }
NodeType *operator->() const { return deref(); }
bool operator==(const IteratorImpl &iter) const { return _idx == iter._idx && _hashmap == iter._hashmap; }
bool operator!=(const IteratorImpl &iter) const { return !(*this == iter); }
IteratorImpl &operator++() {
assert(_hashmap);
do {
_idx++;
} while (_idx <= _hashmap->_mask && (_hashmap->_storage[_idx] == 0 || _hashmap->_storage[_idx] == HASHMAP_DUMMY_NODE));
if (_idx > _hashmap->_mask)
_idx = (size_type)-1;
return *this;
}
IteratorImpl operator++(int) {
IteratorImpl old = *this;
operator ++();
return old;
}
};
public:
typedef IteratorImpl<Node> iterator;
typedef IteratorImpl<const Node> const_iterator;
HashMap();
HashMap(const HM_t &map);
~HashMap();
HM_t &operator=(const HM_t &map) {
if (this == &map)
return *this;
// Remove the previous content and ...
clear();
delete[] _storage;
// ... copy the new stuff.
assign(map);
return *this;
}
bool contains(const Key &key) const;
Val &operator[](const Key &key);
const Val &operator[](const Key &key) const;
Val &getVal(const Key &key);
const Val &getVal(const Key &key) const;
const Val &getVal(const Key &key, const Val &defaultVal) const;
void setVal(const Key &key, const Val &val);
void clear(bool shrinkArray = 0);
void erase(iterator entry);
void erase(const Key &key);
size_type size() const { return _size; }
iterator begin() {
// Find and return the first non-empty entry
for (size_type ctr = 0; ctr <= _mask; ++ctr) {
if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE)
return iterator(ctr, this);
}
return end();
}
iterator end() {
return iterator((size_type)-1, this);
}
const_iterator begin() const {
// Find and return the first non-empty entry
for (size_type ctr = 0; ctr <= _mask; ++ctr) {
if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE)
return const_iterator(ctr, this);
}
return end();
}
const_iterator end() const {
return const_iterator((size_type)-1, this);
}
iterator find(const Key &key) {
size_type ctr = lookup(key);
if (_storage[ctr])
return iterator(ctr, this);
return end();
}
const_iterator find(const Key &key) const {
size_type ctr = lookup(key);
if (_storage[ctr])
return const_iterator(ctr, this);
return end();
}
// TODO: insert() method?
bool empty() const {
return (_size == 0);
}
};
//-------------------------------------------------------
// HashMap functions
/**
* Base constructor, creates an empty hashmap.
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() : _defaultVal() {
_mask = HASHMAP_MIN_CAPACITY - 1;
_storage = new Node *[HASHMAP_MIN_CAPACITY];
assert(_storage != NULL);
memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *));
_size = 0;
_deleted = 0;
#ifdef DEBUG_HASH_COLLISIONS
_collisions = 0;
_lookups = 0;
_dummyHits = 0;
#endif
}
/**
* Copy constructor, creates a full copy of the given hashmap.
* We must provide a custom copy constructor as we use pointers
* to heap buffers for the internal storage.
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
_defaultVal() {
#ifdef DEBUG_HASH_COLLISIONS
_collisions = 0;
_lookups = 0;
_dummyHits = 0;
#endif
assign(map);
}
/**
* Destructor, frees all used memory.
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
for (size_type ctr = 0; ctr <= _mask; ++ctr)
freeNode(_storage[ctr]);
delete[] _storage;
#ifdef DEBUG_HASH_COLLISIONS
extern void updateHashCollisionStats(int, int, int, int, int);
updateHashCollisionStats(_collisions, _dummyHits, _lookups, _mask+1, _size);
#endif
}
/**
* Internal method for assigning the content of another HashMap
* to this one.
*
* @note We do *not* deallocate the previous storage here -- the caller is
* responsible for doing that!
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
_mask = map._mask;
_storage = new Node *[_mask+1];
assert(_storage != NULL);
memset(_storage, 0, (_mask+1) * sizeof(Node *));
// Simply clone the map given to us, one by one.
_size = 0;
_deleted = 0;
for (size_type ctr = 0; ctr <= _mask; ++ctr) {
if (map._storage[ctr] == HASHMAP_DUMMY_NODE) {
_storage[ctr] = HASHMAP_DUMMY_NODE;
_deleted++;
} else if (map._storage[ctr] != NULL) {
_storage[ctr] = allocNode(map._storage[ctr]->_key);
_storage[ctr]->_value = map._storage[ctr]->_value;
_size++;
}
}
// Perform a sanity check (to help track down hashmap corruption)
assert(_size == map._size);
assert(_deleted == map._deleted);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
for (size_type ctr = 0; ctr <= _mask; ++ctr) {
freeNode(_storage[ctr]);
_storage[ctr] = NULL;
}
#ifdef USE_HASHMAP_MEMORY_POOL
_nodePool.freeUnusedPages();
#endif
if (shrinkArray && _mask >= HASHMAP_MIN_CAPACITY) {
delete[] _storage;
_mask = HASHMAP_MIN_CAPACITY;
_storage = new Node *[HASHMAP_MIN_CAPACITY];
assert(_storage != NULL);
memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *));
}
_size = 0;
_deleted = 0;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(size_type newCapacity) {
assert(newCapacity > _mask+1);
#ifndef RELEASE_BUILD
const size_type old_size = _size;
#endif
const size_type old_mask = _mask;
Node **old_storage = _storage;
// allocate a new array
_size = 0;
_deleted = 0;
_mask = newCapacity - 1;
_storage = new Node *[newCapacity];
assert(_storage != NULL);
memset(_storage, 0, newCapacity * sizeof(Node *));
// rehash all the old elements
for (size_type ctr = 0; ctr <= old_mask; ++ctr) {
if (old_storage[ctr] == NULL || old_storage[ctr] == HASHMAP_DUMMY_NODE)
continue;
// Insert the element from the old table into the new table.
// Since we know that no key exists twice in the old table, we
// can do this slightly better than by calling lookup, since we
// don't have to call _equal().
const size_type hash = _hash(old_storage[ctr]->_key);
size_type idx = hash & _mask;
for (size_type perturb = hash; _storage[idx] != NULL && _storage[idx] != HASHMAP_DUMMY_NODE; perturb >>= HASHMAP_PERTURB_SHIFT) {
idx = (5 * idx + perturb + 1) & _mask;
}
_storage[idx] = old_storage[ctr];
_size++;
}
#ifndef RELEASE_BUILD
// Perform a sanity check: Old number of elements should match the new one!
// This check will fail if some previous operation corrupted this hashmap.
assert(_size == old_size);
#endif
delete[] old_storage;
return;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
const size_type hash = _hash(key);
size_type ctr = hash & _mask;
for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
if (_storage[ctr] == NULL)
break;
if (_storage[ctr] == HASHMAP_DUMMY_NODE) {
#ifdef DEBUG_HASH_COLLISIONS
_dummyHits++;
#endif
} else if (_equal(_storage[ctr]->_key, key))
break;
ctr = (5 * ctr + perturb + 1) & _mask;
#ifdef DEBUG_HASH_COLLISIONS
_collisions++;
#endif
}
#ifdef DEBUG_HASH_COLLISIONS
_lookups++;
debug("collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d",
_collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups),
(const void *)this, _mask+1, _size);
#endif
return ctr;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) {
const size_type hash = _hash(key);
size_type ctr = hash & _mask;
const size_type NONE_FOUND = _mask + 1;
size_type first_free = NONE_FOUND;
bool found = false;
for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
if (_storage[ctr] == NULL)
break;
if (_storage[ctr] == HASHMAP_DUMMY_NODE) {
#ifdef DEBUG_HASH_COLLISIONS
_dummyHits++;
#endif
if (first_free != _mask + 1)
first_free = ctr;
} else if (_equal(_storage[ctr]->_key, key)) {
found = true;
break;
}
ctr = (5 * ctr + perturb + 1) & _mask;
#ifdef DEBUG_HASH_COLLISIONS
_collisions++;
#endif
}
#ifdef DEBUG_HASH_COLLISIONS
_lookups++;
debug("collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d",
_collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups),
(const void *)this, _mask+1, _size);
#endif
if (!found && first_free != _mask + 1)
ctr = first_free;
if (!found) {
if (_storage[ctr])
_deleted--;
_storage[ctr] = allocNode(key);
assert(_storage[ctr] != NULL);
_size++;
// Keep the load factor below a certain threshold.
// Deleted nodes are also counted
size_type capacity = _mask + 1;
if ((_size + _deleted) * HASHMAP_LOADFACTOR_DENOMINATOR >
capacity * HASHMAP_LOADFACTOR_NUMERATOR) {
capacity = capacity < 500 ? (capacity * 4) : (capacity * 2);
expandStorage(capacity);
ctr = lookup(key);
assert(_storage[ctr] != NULL);
}
}
return ctr;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
bool HashMap<Key, Val, HashFunc, EqualFunc>::contains(const Key &key) const {
size_type ctr = lookup(key);
return (_storage[ctr] != NULL);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) {
return getVal(key);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) const {
return getVal(key);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) {
size_type ctr = lookupAndCreateIfMissing(key);
assert(_storage[ctr] != NULL);
return _storage[ctr]->_value;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const {
return getVal(key, _defaultVal);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key, const Val &defaultVal) const {
size_type ctr = lookup(key);
if (_storage[ctr] != NULL)
return _storage[ctr]->_value;
else
return defaultVal;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &val) {
size_type ctr = lookupAndCreateIfMissing(key);
assert(_storage[ctr] != NULL);
_storage[ctr]->_value = val;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::erase(iterator entry) {
// Check whether we have a valid iterator
assert(entry._hashmap == this);
const size_type ctr = entry._idx;
assert(ctr <= _mask);
Node * const node = _storage[ctr];
assert(node != NULL);
assert(node != HASHMAP_DUMMY_NODE);
// If we remove a key, we replace it with a dummy node.
freeNode(node);
_storage[ctr] = HASHMAP_DUMMY_NODE;
_size--;
_deleted++;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) {
size_type ctr = lookup(key);
if (_storage[ctr] == NULL)
return;
// If we remove a key, we replace it with a dummy node.
freeNode(_storage[ctr]);
_storage[ctr] = HASHMAP_DUMMY_NODE;
_size--;
_deleted++;
return;
}
#undef HASHMAP_DUMMY_NODE
} // End of namespace Common
#endif

View File

@@ -0,0 +1,246 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "file.h"
#include "map.h"
#define MAP_WIDTH 16
#define MAP_HEIGHT 16
#define FLAG_IS_OUTDOORS 32768
#define MIRROR_COUNT 1
static const MirrorEntry MIRROR_TEXT[MIRROR_COUNT] = {
{ "scummvm", 255, 7, 1, 0 }
};
static const byte MAZE_255[MAP_HEIGHT][MAP_WIDTH] = {
{ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 },
{ 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9 },
{ 9, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 9 },
{ 9, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4,14,14,14,14,14,14, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4,14, 6, 6, 6, 6,14, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4,14, 6, 7, 7, 6,14, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4,14, 6, 7, 7, 6,14, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4,14, 6, 6, 6, 6,14, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4,14,14,14,14,14,14, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 9 },
{ 9, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 9 },
{ 9, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 9 },
{ 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9 },
{ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }
};
static const byte WALL_TYPES_255[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static const byte SURFACE_TYPES_255[16] = { 1, 1, 2, 3, 4, 0, 6, 7, 0, 9, 0, 0, 0, 0, 14, 15 };
/**
* Write out new mirror entries
*/
static void writeMirrorText() {
Common::MemFile f;
for (int idx = 0; idx < MIRROR_COUNT; ++idx) {
const MirrorEntry &me = MIRROR_TEXT[idx];
f.write(me._name, 28);
f.writeByte(me._mapId);
f.writeShort(me._posX);
f.writeShort(me._posY);
f.writeByte(me._direction);
}
Common::File::write("xeenmirr.ext", f);
}
/**
* Write out the maze
*/
static void writeMaze() {
Common::MemFile f;
// Wall data
for (int y = 0; y < MAP_HEIGHT; ++y)
for (int x = 0; x < MAP_WIDTH; ++x)
f.writeWord(MAZE_255[y][x]);
// Surface and flags
for (int y = 0; y < MAP_HEIGHT; ++y)
f.write(MAZE_255[y], MAP_WIDTH);
f.writeWord(255); // Maze number
for (int idx = 0; idx < 4; ++idx)
f.writeWord(0); // No surrounding mazes
f.writeWord(0); // Maze flags 1
f.writeWord(FLAG_IS_OUTDOORS); // Maze flags 2
f.write(WALL_TYPES_255, 16);
f.write(SURFACE_TYPES_255, 16);
f.writeByte(0); // Floor type (unused)
f.writeByte(7); // Run position X
f.writeByte(0, 8); // Difficulties
f.writeByte(0); // Run position Y
f.writeByte(0); // Trap damage
f.writeByte(0); // Wall kind
f.writeByte(0); // Tavern tips
f.writeByte(0, MAP_WIDTH * MAP_HEIGHT / 8); // Seen tiles
f.writeByte(0, MAP_WIDTH * MAP_HEIGHT / 8); // Stepped on tiles
Common::File::write("mazex255.dat", f);
}
/**
* Write out the maze name
*/
static void writeMazeName() {
Common::MemFile f;
char mazeName[33];
memset(mazeName, 0, 33);
strcpy(mazeName, "ScummVM");
f.write(mazeName, 33);
Common::File::write("xeenx255.txt", f);
}
/**
* Write out maze events
*/
static void writeMazeEvents() {
Common::MemFile f;
// Mirror events
static const byte MIRROR_EVENTS[32] = {
6, 7, 0, 2, 0, 40, 1, // Play VOC: "Where to?"
9, 7, 0, 2, 1, 21, 0, 3, 0, 0, // Get destination
5, 7, 0, 2, 2, 18, // Exit
8, 7, 0, 2, 3, 7, 0, 0, 0 // Teleport and exit
};
f.write(MIRROR_EVENTS, 32);
// Bench 1 events
static const byte BENCH1_EVENTS[32] = {
10, 7, 8, 0, 0, 5, 1, 2, 3, 1, 2, // NPC
14, 7, 8, 0, 1, 20, 34, 10000 % 256, 10000 / 256, 0, 0, 0, 0, 0, 0, // Give gold
5, 7, 8, 0, 2, 18 // Exit
};
static const byte BENCH2_EVENTS[30] = {
10, 8, 8, 0, 0, 5, 1, 3, 3, 1, 2, // NPC
14, 8, 8, 0, 1, 20, 35, 1000 % 256, 1000 / 256, 0, 0, 0, 0, // Give gems
5, 8, 8, 0, 2, 18 // Exit
};
f.write(BENCH1_EVENTS, 32);
f.write(BENCH2_EVENTS, 30);
Common::File::write("mazex255.evt", f);
}
/**
* Write out maze event text
*/
static void writeMazeText() {
Common::MemFile f;
f.writeString("Where to?");
f.writeString("Isle of ScummVM");
f.writeString("You have done well to find this ancient isle. This will aid you on your journey.");
f.writeString("It is my hope that this isle will be but the first of many such new destinations the mirror may take you.");
Common::File::write("aazex255.txt", f);
}
/**
* Write out the monster/object data
*/
static void writeMonstersObjects() {
Common::MemFile f;
f.writeByte(8); // Object sprites
f.writeByte(2);
f.writeByte(0xff, 14);
f.writeByte(0xff, 16); // Monster sprites
f.writeByte(0xff, 16); // Wall item sprites
for (int idx = 0; idx < 6; ++idx) {
switch (idx) {
case 0:
// Mirror
f.writeShort(7);
f.writeShort(0);
f.writeByte(0);
f.writeShort(2);
// Benches
f.writeShort(7);
f.writeShort(8);
f.writeShort(1);
f.writeShort(0);
f.writeShort(8);
f.writeShort(8);
f.writeShort(1);
f.writeShort(0);
break;
case 2:
// End of monster/objects
f.writeShort(0);
f.writeShort(0);
f.writeByte(0);
f.writeShort(0);
break;
case 4:
f.writeByte(0x80);
f.writeByte(0x80);
f.writeByte(0);
f.writeShort(0);
break;
default:
f.writeShort(-1);
f.writeShort(-1);
f.writeByte(0xff);
f.writeShort(-1);
break;
}
}
Common::File::write("mazex255.mob", f);
}
/**
* Write out the data for the head danger senses
*/
static void writeHeadData() {
Common::MemFile f;
f.writeByte(0, MAP_HEIGHT * MAP_HEIGHT * 2);
Common::File::write("aazex255.hed", f);
}
/**
* Write out the new ScummVM map
*/
void writeMap() {
writeMirrorText();
writeMaze();
writeMazeName();
writeMazeEvents();
writeMazeText();
writeMonstersObjects();
writeHeadData();
}

View File

@@ -0,0 +1,37 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef MAP_H
#define MAP_H
#include "common/scummsys.h"
#include "cc.h"
struct MirrorEntry {
char _name[28];
byte _mapId;
int8 _posX, _posY;
byte _direction;
};
extern void writeMap();
#endif

View File

@@ -0,0 +1,181 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "memorypool.h"
#include "common/util.h"
namespace Common {
enum {
INITIAL_CHUNKS_PER_PAGE = 8
};
static size_t adjustChunkSize(size_t chunkSize) {
// You must at least fit the pointer in the node (technically unneeded considering the next rounding statement)
chunkSize = MAX(chunkSize, sizeof(void *));
// There might be an alignment problem on some platforms when trying to load a void* on a non natural boundary
// so we round to the next sizeof(void *)
chunkSize = (chunkSize + sizeof(void *) - 1) & (~(sizeof(void *) - 1));
return chunkSize;
}
MemoryPool::MemoryPool(size_t chunkSize)
: _chunkSize(adjustChunkSize(chunkSize)) {
_next = nullptr;
_chunksPerPage = INITIAL_CHUNKS_PER_PAGE;
}
MemoryPool::~MemoryPool() {
#if 0
freeUnusedPages();
if (!_pages.empty())
warning("Memory leak found in pool");
#endif
for (size_t i = 0; i < _pages.size(); ++i)
::free(_pages[i].start);
}
void MemoryPool::allocPage() {
Page page;
// Allocate a new page
page.numChunks = _chunksPerPage;
assert(page.numChunks * _chunkSize < 16*1024*1024); // Refuse to allocate pages bigger than 16 MB
page.start = ::malloc(page.numChunks * _chunkSize);
assert(page.start);
_pages.push_back(page);
// Next time, we'll allocate a page twice as big as this one.
_chunksPerPage *= 2;
// Add the page to the pool of free chunk
addPageToPool(page);
}
void MemoryPool::addPageToPool(const Page &page) {
// Add all chunks of the new page to the linked list (pool) of free chunks
void *current = page.start;
for (size_t i = 1; i < page.numChunks; ++i) {
void *next = (byte *)current + _chunkSize;
*(void **)current = next;
current = next;
}
// Last chunk points to the old _next
*(void **)current = _next;
// From now on, the first free chunk is the first chunk of the new page
_next = page.start;
}
void *MemoryPool::allocChunk() {
// No free chunks left? Allocate a new page
if (!_next)
allocPage();
assert(_next);
void *result = _next;
_next = *(void **)result;
return result;
}
void MemoryPool::freeChunk(void *ptr) {
// Add the chunk back to (the start of) the list of free chunks
*(void **)ptr = _next;
_next = ptr;
}
// Technically not compliant C++ to compare unrelated pointers. In practice...
bool MemoryPool::isPointerInPage(void *ptr, const Page &page) {
return (ptr >= page.start) && (ptr < (char *)page.start + page.numChunks * _chunkSize);
}
void MemoryPool::freeUnusedPages() {
//std::sort(_pages.begin(), _pages.end());
Array<size_t> numberOfFreeChunksPerPage;
numberOfFreeChunksPerPage.resize(_pages.size());
for (size_t i = 0; i < numberOfFreeChunksPerPage.size(); ++i) {
numberOfFreeChunksPerPage[i] = 0;
}
// Compute for each page how many chunks in it are still in use.
void *iterator = _next;
while (iterator) {
// TODO: This should be a binary search (requiring us to keep _pages sorted)
for (size_t i = 0; i < _pages.size(); ++i) {
if (isPointerInPage(iterator, _pages[i])) {
++numberOfFreeChunksPerPage[i];
break;
}
}
iterator = *(void **)iterator;
}
// Free all pages which are not in use.
size_t freedPagesCount = 0;
for (size_t i = 0; i < _pages.size(); ++i) {
if (numberOfFreeChunksPerPage[i] == _pages[i].numChunks) {
// Remove all chunks of this page from the list of free chunks
void **iter2 = &_next;
while (*iter2) {
if (isPointerInPage(*iter2, _pages[i]))
*iter2 = **(void ***)iter2;
else
iter2 = *(void ***)iter2;
}
::free(_pages[i].start);
++freedPagesCount;
_pages[i].start = nullptr;
}
}
// debug("freed %d pages out of %d", (int)freedPagesCount, (int)_pages.size());
// Remove all now unused pages
size_t newSize = 0;
for (size_t i = 0; i < _pages.size(); ++i) {
if (_pages[i].start != nullptr) {
if (newSize != i)
_pages[newSize] = _pages[i];
++newSize;
}
}
_pages.resize(newSize);
// Reset _chunksPerPage
_chunksPerPage = INITIAL_CHUNKS_PER_PAGE;
for (size_t i = 0; i < _pages.size(); ++i) {
if (_chunksPerPage < _pages[i].numChunks)
_chunksPerPage = _pages[i].numChunks;
}
}
} // End of namespace Common

View File

@@ -0,0 +1,161 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef COMMON_MEMORYPOOL_H
#define COMMON_MEMORYPOOL_H
#include "common/array.h"
namespace Common {
/**
* This class provides a pool of memory 'chunks' of identical size.
* The size of a chunk is determined when creating the memory pool.
*
* Using a memory pool may yield better performance and memory usage
* when allocating and deallocating many memory blocks of equal size.
* E.g. the Common::String class uses a memory pool for the refCount
* variables (each the size of an int) it allocates for each string
* instance.
*/
class MemoryPool {
protected:
MemoryPool(const MemoryPool&);
MemoryPool& operator=(const MemoryPool&);
struct Page {
void *start;
size_t numChunks;
};
const size_t _chunkSize;
Array<Page> _pages;
void *_next;
size_t _chunksPerPage;
void allocPage();
void addPageToPool(const Page &page);
bool isPointerInPage(void *ptr, const Page &page);
public:
/**
* Constructor for a memory pool with the given chunk size.
* @param chunkSize the chunk size of this memory pool
*/
explicit MemoryPool(size_t chunkSize);
~MemoryPool();
/**
* Allocate a new chunk from the memory pool.
*/
void *allocChunk();
/**
* Return a chunk to the memory pool. The given pointer must have
* been obtained from calling the allocChunk() method of the very
* same MemoryPool instance. Passing any other pointer (e.g. to
* a chunk from another MemoryPool, or a malloc'ed memory block)
* will lead to undefined behavior and may result in a crash (if
* you are lucky) or in silent data corruption.
*/
void freeChunk(void *ptr);
/**
* Perform garbage collection. The memory pool stores all the
* chunks it manages in memory 'pages' obtained via the classic
* memory allocation APIs (i.e. malloc/free). Ordinarily, once
* a page has been allocated, it won't be released again during
* the life time of the memory pool. The exception is when this
* method is called.
*/
void freeUnusedPages();
/**
* Return the chunk size used by this memory pool.
*/
size_t getChunkSize() const { return _chunkSize; }
};
/**
* This is a memory pool which already contains in itself some storage
* space for a fixed number of chunks. Thus if the memory pool is only
* lightly used, no malloc() calls have to be made at all.
*/
template<size_t CHUNK_SIZE, size_t NUM_INTERNAL_CHUNKS = 32>
class FixedSizeMemoryPool : public MemoryPool {
private:
enum {
REAL_CHUNK_SIZE = (CHUNK_SIZE + sizeof(void *) - 1) & (~(sizeof(void *) - 1))
};
byte _storage[NUM_INTERNAL_CHUNKS * REAL_CHUNK_SIZE];
public:
FixedSizeMemoryPool() : MemoryPool(CHUNK_SIZE) {
assert(REAL_CHUNK_SIZE == _chunkSize);
// Insert some static storage
Page internalPage = { _storage, NUM_INTERNAL_CHUNKS };
addPageToPool(internalPage);
}
};
// Ensure NUM_INTERNAL_CHUNKS == 0 results in a compile error
template<size_t CHUNK_SIZE>
class FixedSizeMemoryPool<CHUNK_SIZE,0> : public MemoryPool {
public:
FixedSizeMemoryPool() : MemoryPool(CHUNK_SIZE) {}
};
/**
* A memory pool for C++ objects.
*/
template<class T, size_t NUM_INTERNAL_CHUNKS = 32>
class ObjectPool : public FixedSizeMemoryPool<sizeof(T), NUM_INTERNAL_CHUNKS> {
public:
/**
* Return the memory chunk used as storage for the given object back
* to the pool, after calling its destructor.
*/
void deleteChunk(T *ptr) {
ptr->~T();
this->freeChunk(ptr);
}
};
} // End of namespace Common
/**
* A custom placement new operator, using an arbitrary MemoryPool.
*
* This *should* work with all C++ implementations, but may not.
*
* For details on using placement new for custom allocators, see e.g.
* <https://isocpp.org/wiki/faq/dtors#memory-pools>
*/
inline void *operator new(size_t nbytes, Common::MemoryPool &pool) {
assert(nbytes <= pool.getChunkSize());
return pool.allocChunk();
}
inline void operator delete(void *p, Common::MemoryPool &pool) {
pool.freeChunk(p);
}
#endif

View File

@@ -0,0 +1,18 @@
MODULE := devtools/create_mm/create_xeen
MODULE_OBJS := \
create_xeen.o \
cc.o \
clouds.o \
constants.o \
hashmap.o \
map.o \
memorypool.o \
str.o \
swords.o
# Set the name of the executable
TOOL_EXECUTABLE := create_xeen
# Include common rules
include $(srcdir)/rules.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
#define SCUMMVM_UTIL
#include "../../../common/str-base.cpp"
#include "../../../common/str.cpp"

View File

@@ -0,0 +1,385 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef COMMON_STRING_H
#define COMMON_STRING_H
#include "common/scummsys.h"
#include <stdarg.h>
namespace Common {
/**
* Simple string class for ScummVM. Provides automatic storage management,
* and overloads several operators in a 'natural' fashion, mimicking
* the std::string class. Even provides simple iterators.
*
* This class tries to avoid allocating lots of small blocks on the heap,
* since that is inefficient on several platforms supported by ScummVM.
* Instead, small strings are stored 'inside' the string object (i.e. on
* the stack, for stack allocated objects), and only for strings exceeding
* a certain length do we allocate a buffer on the heap.
*
* The presence of \0 characters in the string will cause undefined
* behavior in some operations.
*/
class String {
public:
static const uint32 npos = 0xFFFFFFFF;
protected:
/**
* The size of the internal storage. Increasing this means less heap
* allocations are needed, at the cost of more stack memory usage,
* and of course lots of wasted memory. Empirically, 90% or more of
* all String instances are less than 32 chars long. If a platform
* is very short on stack space, it would be possible to lower this.
* A value of 24 still seems acceptable, though considerably worse,
* while 16 seems to be the lowest you want to go... Anything lower
* than 8 makes no sense, since that's the size of member _extern
* (on 32 bit machines; 12 bytes on systems with 64bit pointers).
*/
static const uint32 _builtinCapacity = 32 - sizeof(uint32) - sizeof(char *);
/**
* Length of the string. Stored to avoid having to call strlen
* a lot. Yes, we limit ourselves to strings shorter than 4GB --
* on purpose :-).
*/
uint32 _size;
/**
* Pointer to the actual string storage. Either points to _storage,
* or to a block allocated on the heap via malloc.
*/
char *_str;
union {
/**
* Internal string storage.
*/
char _storage[_builtinCapacity];
/**
* External string storage data -- the refcounter, and the
* capacity of the string _str points to.
*/
struct {
mutable int *_refCount;
uint32 _capacity;
} _extern;
};
inline bool isStorageIntern() const {
return _str == _storage;
}
public:
/** Construct a new empty string. */
String() : _size(0), _str(_storage) { _storage[0] = 0; }
/** Construct a new string from the given NULL-terminated C string. */
String(const char *str);
/** Construct a new string containing exactly len characters read from address str. */
String(const char *str, uint32 len);
/** Construct a new string containing the characters between beginP (including) and endP (excluding). */
String(const char *beginP, const char *endP);
/** Construct a copy of the given string. */
String(const String &str);
/** Construct a string consisting of the given character. */
explicit String(char c);
~String();
String &operator=(const char *str);
String &operator=(const String &str);
String &operator=(char c);
String &operator+=(const char *str);
String &operator+=(const String &str);
String &operator+=(char c);
bool operator==(const String &x) const;
bool operator==(const char *x) const;
bool operator!=(const String &x) const;
bool operator!=(const char *x) const;
bool operator<(const String &x) const;
bool operator<=(const String &x) const;
bool operator>(const String &x) const;
bool operator>=(const String &x) const;
bool equals(const String &x) const;
bool equalsIgnoreCase(const String &x) const;
int compareTo(const String &x) const; // strcmp clone
int compareToIgnoreCase(const String &x) const; // stricmp clone
bool equals(const char *x) const;
bool equalsIgnoreCase(const char *x) const;
int compareTo(const char *x) const; // strcmp clone
int compareToIgnoreCase(const char *x) const; // stricmp clone
bool hasSuffix(const String &x) const;
bool hasSuffix(const char *x) const;
bool hasPrefix(const String &x) const;
bool hasPrefix(const char *x) const;
bool contains(const String &x) const;
bool contains(const char *x) const;
bool contains(char x) const;
inline const char *c_str() const { return _str; }
inline uint size() const { return _size; }
inline bool empty() const { return (_size == 0); }
char firstChar() const { return (_size > 0) ? _str[0] : 0; }
char lastChar() const { return (_size > 0) ? _str[_size - 1] : 0; }
char operator[](int idx) const {
assert(_str && idx >= 0 && idx < (int)_size);
return _str[idx];
}
/** Remove the last character from the string. */
void deleteLastChar();
/** Remove the character at position p from the string. */
void deleteChar(uint32 p);
/** Remove all characters from position p to the p + len. If len = String::npos, removes all characters to the end */
void erase(uint32 p, uint32 len = npos);
/** Set character c at position p, replacing the previous character there. */
void setChar(char c, uint32 p);
/** Insert character c before position p. */
void insertChar(char c, uint32 p);
/** Clears the string, making it empty. */
void clear();
/** Convert all characters in the string to lowercase. */
void toLowercase();
/** Convert all characters in the string to uppercase. */
void toUppercase();
/**
* Removes trailing and leading whitespaces. Uses isspace() to decide
* what is whitespace and what not.
*/
void trim();
uint hash() const;
/**
* Print formatted data into a String object. Similar to sprintf,
* except that it stores the result in (variably sized) String
* instead of a fixed size buffer.
*/
static String format(const char *fmt, ...) GCC_PRINTF(1,2);
/**
* Print formatted data into a String object. Similar to vsprintf,
* except that it stores the result in (variably sized) String
* instead of a fixed size buffer.
*/
static String vformat(const char *fmt, va_list args);
public:
typedef char value_type;
/**
* Unsigned version of the underlying type. This can be used to cast
* individual string characters to bigger integer types without sign
* extension happening.
*/
typedef unsigned char unsigned_type;
typedef char * iterator;
typedef const char * const_iterator;
iterator begin() {
// Since the user could potentially
// change the string via the returned
// iterator we have to assure we are
// pointing to a unique storage.
makeUnique();
return _str;
}
iterator end() {
return begin() + size();
}
const_iterator begin() const {
return _str;
}
const_iterator end() const {
return begin() + size();
}
protected:
void makeUnique();
void ensureCapacity(uint32 new_size, bool keep_old);
void incRefCount() const;
void decRefCount(int *oldRefCount);
void initWithCStr(const char *str, uint32 len);
};
// Append two strings to form a new (temp) string
String operator+(const String &x, const String &y);
String operator+(const char *x, const String &y);
String operator+(const String &x, const char *y);
String operator+(const String &x, char y);
String operator+(char x, const String &y);
// Some useful additional comparison operators for Strings
bool operator==(const char *x, const String &y);
bool operator!=(const char *x, const String &y);
// Utility functions to remove leading and trailing whitespaces
extern char *ltrim(char *t);
extern char *rtrim(char *t);
extern char *trim(char *t);
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return 'bar.txt'
* /foo/bar/ would return 'bar'
* /foo/./bar// would return 'bar'
*
* @param path the path of which we want to know the last component
* @param sep character used to separate path components
* @return The last component of the path.
*/
String lastPathComponent(const String &path, const char sep);
/**
* Normalize a given path to a canonical form. In particular:
* - trailing separators are removed: /foo/bar/ -> /foo/bar
* - double separators (= empty components) are removed: /foo//bar -> /foo/bar
* - dot components are removed: /foo/./bar -> /foo/bar
*
* @todo remove double dot components: /foo/baz/../bar -> /foo/bar
*
* @param path the path to normalize
* @param sep the separator token (usually '/' on Unix-style systems, or '\\' on Windows based stuff)
* @return the normalized path
*/
String normalizePath(const String &path, const char sep);
/**
* Simple DOS-style pattern matching function (understands * and ? like used in DOS).
* Taken from exult/files/listfiles.cc
*
* Token meaning:
* "*": any character, any amount of times.
* "?": any character, only once.
* "#": any decimal digit, only once.
*
* Example strings/patterns:
* String: monkey.s01 Pattern: monkey.s?? => true
* String: monkey.s101 Pattern: monkey.s?? => false
* String: monkey.s99 Pattern: monkey.s?1 => false
* String: monkey.s101 Pattern: monkey.s* => true
* String: monkey.s99 Pattern: monkey.s*1 => false
* String: monkey.s01 Pattern: monkey.s## => true
* String: monkey.s01 Pattern: monkey.### => false
*
* @param str Text to be matched against the given pattern.
* @param pat Glob pattern.
* @param ignoreCase Whether to ignore the case when doing pattern match
* @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly.
*
* @return true if str matches the pattern, false otherwise.
*/
bool matchString(const char *str, const char *pat, bool ignoreCase = false, bool pathMode = false);
/**
* Take a 32 bit value and turn it into a four character string, where each of
* the four bytes is turned into one character. Most significant byte is printed
* first.
*/
String tag2string(uint32 tag);
/**
* Copy up to size - 1 characters from src to dst and also zero terminate the
* result. Note that src must be a zero terminated string.
*
* In case size is zero this function just returns the length of the source
* string.
*
* @note This is modeled after OpenBSD's strlcpy. See the manpage here:
* https://man.openbsd.org/strlcpy
*
* @param dst The destination buffer.
* @param src The source string.
* @param size The size of the destination buffer.
* @return The length of the (non-truncated) result, i.e. strlen(src).
*/
size_t strlcpy(char *dst, const char *src, size_t size);
/**
* Append the string src to the string dst. Note that both src and dst must be
* zero terminated. The result will be zero terminated. At most
* "size - strlen(dst) - 1" bytes will be appended.
*
* In case the dst string does not contain a zero within the first "size" bytes
* the dst string will not be changed and size + strlen(src) is returned.
*
* @note This is modeled after OpenBSD's strlcat. See the manpage here:
* https://man.openbsd.org/strlcat
*
* @param dst The string the source string should be appended to.
* @param src The source string.
* @param size The (total) size of the destination buffer.
* @return The length of the (non-truncated) result. That is
* strlen(dst) + strlen(src). In case strlen(dst) > size
* size + strlen(src) is returned.
*/
size_t strlcat(char *dst, const char *src, size_t size);
/**
* Convenience wrapper for tag2string which "returns" a C string.
* Note: It is *NOT* safe to do anything with the return value other than directly
* copying or printing it.
*/
#define tag2str(x) Common::tag2string(x).c_str()
} // End of namespace Common
extern int scumm_stricmp(const char *s1, const char *s2);
extern int scumm_strnicmp(const char *s1, const char *s2, uint n);
#endif

View File

@@ -0,0 +1,53 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "file.h"
#include "swords.h"
#define MONSTERS_COUNT 151
extern void NORETURN_PRE error(const char *s, ...);
void writeSwordsData(const char *swordsDatName) {
Common::File f;
Common::MemFile monsters;
const int size = MONSTERS_COUNT * 60;
const int32 offset = 0x44200;
byte buffer[size];
if (!f.open(swordsDatName, Common::kFileReadMode))
error("Could not open '%s'", swordsDatName);
if (f.seek(offset) != 0)
error("Failed to seek to 0x%x for '%s'", offset, swordsDatName);
if (f.read(buffer, size) != size)
error("Failed to read %d bytes from '%s'", size, swordsDatName);
if (strcmp((const char *)buffer + 0x33, "Slime"))
error("Invalid '%s'", swordsDatName);
monsters.write(buffer, size);
Common::File::write("monsters.swd", monsters);
}

View File

@@ -0,0 +1,27 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef SWORDS_H
#define SWORDS_H
extern void writeSwordsData(const char *swordsDatName);
#endif