aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dists/engine-data/kyra.datbin331978 -> 344846 bytes
-rw-r--r--engines/kyra/resource.h15
-rw-r--r--engines/kyra/staticres.cpp368
-rw-r--r--tools/create_kyradat/create_kyradat.cpp91
-rw-r--r--tools/create_kyradat/create_kyradat.h4
5 files changed, 127 insertions, 351 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index 0574553fd4..f96675f74f 100644
--- a/dists/engine-data/kyra.dat
+++ b/dists/engine-data/kyra.dat
Binary files differ
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 294cb932f7..81987306e0 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -103,7 +103,7 @@ enum KyraResources {
kLoadAll = -1,
// This list has to match orderwise (and thus value wise) the static data list of "tools/create_kyradat/create_kyradat.h"!
- k1ForestSeq,
+ k1ForestSeq = 1,
k1KallakWritingSeq,
k1KyrandiaLogoSeq,
k1KallakMalcolmSeq,
@@ -348,7 +348,7 @@ class StaticResource {
public:
static const Common::String staticDataFilename() { return "KYRA.DAT"; }
- StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _dataTable(0) {}
+ StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _dataTable() {}
~StaticResource() { deinit(); }
bool loadStaticResourceFile();
@@ -469,7 +469,16 @@ private:
Common::List<ResData> _resList;
const FileType *_fileLoader;
- const int *_dataTable;
+
+ struct DataDescriptor {
+ DataDescriptor() : filename(0), type(0) {}
+ DataDescriptor(uint32 f, uint8 t) : filename(f), type(t) {}
+
+ uint32 filename;
+ uint8 type;
+ };
+ typedef Common::HashMap<uint16, DataDescriptor> DataMap;
+ DataMap _dataTable;
};
} // End of namespace Kyra
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 918df6fc7d..0b3979f570 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -45,7 +45,7 @@
namespace Kyra {
-#define RESFILE_VERSION 68
+#define RESFILE_VERSION 69
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -91,12 +91,12 @@ byte getGameID(const GameFlags &flags) {
}
const IndexTable iLanguageTable[] = {
- { Common::EN_ANY, 0 },
- { Common::FR_FRA, 1 },
- { Common::DE_DEU, 2 },
- { Common::ES_ESP, 3 },
- { Common::IT_ITA, 4 },
- { Common::JA_JPN, 5 },
+ { Common::EN_ANY, 1 },
+ { Common::FR_FRA, 2 },
+ { Common::DE_DEU, 3 },
+ { Common::ES_ESP, 4 },
+ { Common::IT_ITA, 5 },
+ { Common::JA_JPN, 6 },
{ -1, -1 }
};
@@ -192,9 +192,13 @@ bool StaticResource::tryKyraDatLoad() {
return false;
}
- const uint16 gameDef = ((getGameID(_vm->gameFlags()) & 0xF) << 12) |
- ((getPlatformID(_vm->gameFlags()) & 0xF) << 8) |
- ((getSpecialID(_vm->gameFlags()) & 0xF) << 4);
+ const GameFlags &flags = _vm->gameFlags();
+ const byte game = getGameID(flags) & 0xF;
+ const byte platform = getPlatformID(flags) & 0xF;
+ const byte special = getSpecialID(flags) & 0xF;
+ const byte lang = getLanguageID(flags) & 0xF;
+
+ const uint16 gameDef = (game << 12) | (platform << 8) | (special << 4) | (lang << 0);
bool found = false;
for (uint32 i = 0; i < includedGames; ++i) {
@@ -210,6 +214,26 @@ bool StaticResource::tryKyraDatLoad() {
if (!found)
return false;
+ // load the ID map for our game
+ const Common::String filenamePattern = Common::String::printf("0%01X%01X%01X%03X%01X", game, platform, special, 0, lang);
+ Common::SeekableReadStream *idMap = _vm->resource()->createReadStream(filenamePattern);
+ if (!idMap)
+ return false;
+
+ uint16 numIDs = idMap->readUint16BE();
+ while (numIDs--) {
+ uint16 id = idMap->readUint16BE();
+ uint8 type = idMap->readByte();
+ uint32 filename = idMap->readUint32BE();
+
+ _dataTable[id] = DataDescriptor(filename, type);
+ }
+
+ const bool fileError = idMap->err();
+ delete idMap;
+ if (fileError)
+ return false;
+
// load all tables for now
if (!prefetchId(-1))
return false;
@@ -245,288 +269,6 @@ bool StaticResource::init() {
#undef proc
_fileLoader = fileTypeTable;
- // Kyrandia 1 Filenames
- static const int kyra1StaticRes[] = {
- // INTRO / OUTRO sequences
- k1ForestSeq,
- k1KallakWritingSeq,
- k1KyrandiaLogoSeq,
- k1KallakMalcolmSeq,
- k1MalcolmTreeSeq,
- k1WestwoodLogoSeq,
- k1Demo1Seq,
- k1Demo2Seq,
- k1Demo3Seq,
- k1Demo4Seq,
- k1OutroReunionSeq,
-
- // INTRO / OUTRO strings
- k1IntroCPSStrings,
- k1IntroCOLStrings,
- k1IntroWSAStrings,
- k1IntroStrings,
- k1OutroHomeString,
-
- // INGAME strings
- k1ItemNames,
- k1TakenStrings,
- k1PlacedStrings,
- k1DroppedStrings,
- k1NoDropStrings,
- k1PutDownString,
- k1WaitAmuletString,
- k1BlackJewelString,
- k1PoisonGoneString,
- k1HealingTipString,
- k1ThePoisonStrings,
- k1FluteStrings,
- k1WispJewelStrings,
- k1MagicJewelStrings,
- k1FlaskFullString,
- k1FullFlaskString,
- k1VeryCleverString,
- k1NewGameString,
-
- // GUI strings table
- k1GUIStrings,
- k1ConfigStrings,
-
- // ROOM table/filenames
- k1RoomList,
- k1RoomFilenames,
-
- // SHAPE tables
- k1DefaultShapes,
- k1Healing1Shapes,
- k1Healing2Shapes,
- k1PoisonDeathShapes,
- k1FluteShapes,
- k1Winter1Shapes,
- k1Winter2Shapes,
- k1Winter3Shapes,
- k1DrinkShapes,
- k1WispShapes,
- k1MagicAnimShapes,
- k1BranStoneShapes,
-
- // IMAGE filename table
- k1CharacterImageFilenames,
-
- // AMULET anim
- k1AmuleteAnimSeq,
-
- // PALETTE table
- k1SpecialPalette1,
- k1SpecialPalette2,
- k1SpecialPalette3,
- k1SpecialPalette4,
- k1SpecialPalette5,
- k1SpecialPalette6,
- k1SpecialPalette7,
- k1SpecialPalette8,
- k1SpecialPalette9,
- k1SpecialPalette10,
- k1SpecialPalette11,
- k1SpecialPalette12,
- k1SpecialPalette13,
- k1SpecialPalette14,
- k1SpecialPalette15,
- k1SpecialPalette16,
- k1SpecialPalette17,
- k1SpecialPalette18,
- k1SpecialPalette19,
- k1SpecialPalette20,
- k1SpecialPalette21,
- k1SpecialPalette22,
- k1SpecialPalette23,
- k1SpecialPalette24,
- k1SpecialPalette25,
- k1SpecialPalette26,
- k1SpecialPalette27,
- k1SpecialPalette28,
- k1SpecialPalette29,
- k1SpecialPalette30,
- k1SpecialPalette31,
- k1SpecialPalette32,
- k1SpecialPalette33,
-
- // AUDIO files
- k1AudioTracks,
- k1AudioTracksIntro,
-
- // FM-TOWNS specific
- k1TownsSFXwdTable,
- k1TownsSFXbtTable,
- k1TownsCDATable,
-
- // PC98 specific
- k1PC98StoryStrings,
- k1PC98IntroSfx,
-
- // CREDITS (used in FM-TOWNS and AMIGA)
- k1CreditsStrings,
-
- // AMIGA specific
- k1AmigaIntroSFXTable,
- k1AmigaGameSFXTable,
-
- -1
- };
-
- static const int kyra2StaticRes[] = {
- // Sequence Player
- k2SeqplayPakFiles,
- k2SeqplayCredits,
- k2SeqplayCreditsSpecial,
- k2SeqplayStrings,
- k2SeqplaySfxFiles,
- k2SeqplayTlkFiles,
- k2SeqplaySeqData,
- k2SeqplayIntroTracks,
- k2SeqplayFinaleTracks,
- k2SeqplayIntroCDA,
- k2SeqplayFinaleCDA,
- k2SeqplayShapeAnimData,
-
- // Ingame
- k2IngamePakFiles,
- k2IngameSfxFiles,
- k2IngameSfxIndex,
- k2IngameTracks,
- k2IngameCDA,
- k2IngameTalkObjIndex,
- k2IngameTimJpStrings,
- k2IngameShapeAnimData,
- k2IngameTlkDemoStrings,
-
- -1
- };
-
- static const int kyra3StaticRes[] = {
- k3MainMenuStrings,
- k3MusicFiles,
- k3ScoreTable,
- k3SfxFiles,
- k3SfxMap,
- k3ItemAnimData,
- k3ItemMagicTable,
- k3ItemStringMap,
-
- -1
- };
-
-#ifdef ENABLE_LOL
- static const int kLolStaticRes[] = {
- // Demo Sequence Player
- k2SeqplayPakFiles,
- k2SeqplayStrings,
- k2SeqplaySfxFiles,
- k2SeqplaySeqData,
- k2SeqplayIntroTracks,
-
- // Ingame
- kLolIngamePakFiles,
-
- kLolCharacterDefs,
- kLolIngameSfxFiles,
- kLolIngameSfxIndex,
- kLolMusicTrackMap,
- kLolIngameGMSfxIndex,
- kLolIngameMT32SfxIndex,
- kLolIngamePcSpkSfxIndex,
- kLolSpellProperties,
- kLolGameShapeMap,
- kLolSceneItemOffs,
- kLolCharInvIndex,
- kLolCharInvDefs,
- kLolCharDefsMan,
- kLolCharDefsWoman,
- kLolCharDefsKieran,
- kLolCharDefsAkshel,
- kLolExpRequirements,
- kLolMonsterModifiers,
- kLolMonsterShiftOffsets,
- kLolMonsterDirFlags,
- kLolMonsterScaleY,
- kLolMonsterScaleX,
- kLolMonsterScaleWH,
- kLolFlyingObjectShp,
- kLolInventoryDesc,
-
- kLolLevelShpList,
- kLolLevelDatList,
- kLolCompassDefs,
- kLolItemPrices,
- kLolStashSetup,
-
- kLolDscUnk1,
- kLolDscShapeIndex,
- kLolDscOvlMap,
- kLolDscScaleWidthData,
- kLolDscScaleHeightData,
- kLolDscX,
- kLolDscY,
- kLolDscTileIndex,
- kLolDscUnk2,
- kLolDscDoorShapeIndex,
- kLolDscDimData1,
- kLolDscDimData2,
- kLolDscBlockMap,
- kLolDscDimMap,
- kLolDscDoorScale,
- kLolDscDoor4,
- kLolDscOvlIndex,
- kLolDscBlockIndex,
- kLolDscDoor1,
- kLolDscDoorX,
- kLolDscDoorY,
-
- kLolScrollXTop,
- kLolScrollYTop,
- kLolScrollXBottom,
- kLolScrollYBottom,
-
- kLolButtonDefs,
- kLolButtonList1,
- kLolButtonList2,
- kLolButtonList3,
- kLolButtonList4,
- kLolButtonList5,
- kLolButtonList6,
- kLolButtonList7,
- kLolButtonList8,
-
- kLolLegendData,
- kLolMapCursorOvl,
- kLolMapStringId,
-
- kLolSpellbookAnim,
- kLolSpellbookCoords,
- kLolHealShapeFrames,
- kLolLightningDefs,
- kLolFireballCoords,
-
- kLolCredits,
-
- kLolHistory,
-
- -1
- };
-#endif // ENABLE_LOL
-
- if (_vm->game() == GI_KYRA1)
- _dataTable = kyra1StaticRes;
- else if (_vm->game() == GI_KYRA2)
- _dataTable = kyra2StaticRes;
- else if (_vm->game() == GI_KYRA3)
- _dataTable = kyra3StaticRes;
-#ifdef ENABLE_LOL
- else if (_vm->game() == GI_LOL)
- _dataTable = kLolStaticRes;
-#endif // ENABLE_LOL
- else
- error("StaticResource: Unknown game ID");
-
return loadStaticResourceFile();
}
@@ -598,8 +340,10 @@ const ButtonDef *StaticResource::loadButtonDefs(int id, int &entries) {
bool StaticResource::prefetchId(int id) {
if (id == -1) {
- for (int i = 0; _dataTable[i] != -1; ++i)
- prefetchId(_dataTable[i]);
+ for (DataMap::const_iterator i = _dataTable.begin(); i != _dataTable.end(); ++i) {
+ if (!prefetchId(i->_key))
+ return false;
+ }
return true;
}
@@ -609,44 +353,18 @@ bool StaticResource::prefetchId(int id) {
if (checkResList(id, type, ptr, size))
return true;
- const GameFlags &flags = _vm->gameFlags();
- byte game = getGameID(flags);
- byte platform = getPlatformID(flags);
- byte special = getSpecialID(flags);
- byte lang = getLanguageID(flags);
-
- Common::ArchiveMemberList fileCandidates;
-
- const Common::String filenamePattern = Common::String::printf("%01X%01X%01X??%03X", game, platform, special, id);
- const Common::String langFilenamePattern = filenamePattern + Common::String::printf("%01X", lang);
-
- // We assume the order of "fileCandidates" never changes across these calls. This means:
- // The filenames matching "filenamePattern" will be added after the ones matching
- // "langFilenamePattern".
- _vm->resource()->listFiles(langFilenamePattern.c_str(), fileCandidates);
- _vm->resource()->listFiles(filenamePattern.c_str(), fileCandidates);
-
- if (fileCandidates.empty())
+ DataMap::const_iterator dDesc = _dataTable.find(id);
+ if (dDesc == _dataTable.end())
return false;
- // First entry in the list should be the one we want
- Common::ArchiveMemberPtr file = *fileCandidates.begin();
- fileCandidates.clear();
-
- unsigned int rType = (unsigned int)-1;
- if (sscanf(file->getDisplayName().c_str(), "%*01X%*01X%*01X%02X%*03X", &rType) != 1) {
- warning("Failed to parse filename from kyra.dat: \"%s\"", file->getDisplayName().c_str());
- return false;
- }
-
- const FileType *filetype = getFiletype(rType);
+ const FileType *filetype = getFiletype(dDesc->_value.type);
if (!filetype)
return false;
ResData data;
data.id = id;
- data.type = rType;
- Common::SeekableReadStream *fileStream = file->createReadStream();
+ data.type = dDesc->_value.type;
+ Common::SeekableReadStream *fileStream = _vm->resource()->createReadStream(Common::String::printf("%08X", dDesc->_value.filename));
if (!fileStream)
return false;
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index f6b768ec43..ae498992c2 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -42,10 +42,13 @@
#include <map>
enum {
- kKyraDatVersion = 68
+ kKyraDatVersion = 69
};
const ExtractFilename extractFilenames[] = {
+ // GENERIC ID MAP
+ { kIdMap, -1, true },
+
// INTRO / OUTRO sequences
{ k1ForestSeq, kTypeRawData, false },
{ k1KallakWritingSeq, kTypeRawData, false },
@@ -327,12 +330,13 @@ byte getGameID(int game) {
}
const TypeTable languageTable[] = {
- { EN_ANY, 0 },
- { FR_FRA, 1 },
- { DE_DEU, 2 },
- { ES_ESP, 3 },
- { IT_ITA, 4 },
- { JA_JPN, 5 },
+ { UNK_LANG, 0 },
+ { EN_ANY, 1 },
+ { FR_FRA, 2 },
+ { DE_DEU, 3 },
+ { ES_ESP, 4 },
+ { IT_ITA, 5 },
+ { JA_JPN, 6 },
{ -1, -1 }
};
@@ -367,17 +371,23 @@ byte getSpecialID(int special) {
// filename processing
-bool getFilename(char *dstFilename, const ExtractInformation *info, const int id) {
- const ExtractFilename *i = getFilenameDesc(id);
+uint32 getFilename(const ExtractInformation *info, const int id) {
+ const ExtractFilename *fDesc = getFilenameDesc(id);
- if (!i)
- return false;
+ if (!fDesc)
+ return 0;
+
+ // GAME, PLATFORM, SPECIAL, ID, LANG
+ return ((getGameID(info->game) & 0xF) << 24) |
+ ((getPlatformID(info->platform) & 0xF) << 20) |
+ ((getSpecialID(info->special) & 0xF) << 16) |
+ ((id & 0xFFF) << 4) |
+ ((getLanguageID(fDesc->langSpecific ? info->lang : UNK_LANG) & 0xF) << 0);
+}
- // GAME, PLATFORM, SPECIAL, TYPE, ID[, LANG]
- if (i->langSpecific)
- sprintf(dstFilename, "%01X%01X%01X%02X%03X%01X", getGameID(info->game), getPlatformID(info->platform), getSpecialID(info->special), getTypeID(i->type), id, getLanguageID(info->lang));
- else
- sprintf(dstFilename, "%01X%01X%01X%02X%03X", getGameID(info->game), getPlatformID(info->platform), getSpecialID(info->special), getTypeID(i->type), id);
+// TODO: Get rid of this
+bool getFilename(char *dstFilename, const ExtractInformation *info, const int id) {
+ sprintf(dstFilename, "%08X", getFilename(info, id));
return true;
}
@@ -388,7 +398,8 @@ typedef uint16 GameDef;
GameDef createGameDef(const ExtractInformation *eI) {
return ((getGameID(eI->game) & 0xF) << 12) |
((getPlatformID(eI->platform) & 0xF) << 8) |
- ((getSpecialID(eI->special) & 0xF) << 4);
+ ((getSpecialID(eI->special) & 0xF) << 4) |
+ ((getLanguageID(eI->lang) & 0xF) << 0);
}
struct Index {
@@ -1127,6 +1138,8 @@ typedef std::multimap<int, ExtractData> ExtractMap;
bool getExtractionData(const Game *g, Search &search, ExtractMap &map);
+bool createIDMap(PAKFile &out, const ExtractInformation *eI, const int *needList);
+
bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
char filename[128];
@@ -1149,6 +1162,7 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
for (ExtractMap::const_iterator i = ids.begin(); i != ids.end(); ++i) {
const int id = i->first;
+ extractInfo.lang = i->second.desc.lang;
const ExtractFilename *fDesc = getFilenameDesc(id);
@@ -1157,11 +1171,6 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
return false;
}
- if (fDesc->langSpecific)
- extractInfo.lang = i->second.desc.lang;
- else
- extractInfo.lang = UNK_LANG;
-
filename[0] = 0;
if (!getFilename(filename, &extractInfo, id)) {
fprintf(stderr, "ERROR: couldn't get filename for id %d/%s\n", id, getIdString(id));
@@ -1190,6 +1199,9 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
continue;
extractInfo.lang = g->lang[i];
+ if (!createIDMap(out, &extractInfo, needList))
+ return false;
+
if (!updateIndex(out, &extractInfo)) {
error("couldn't update INDEX file, stop processing of all files");
return false;
@@ -1199,6 +1211,41 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
return true;
}
+bool createIDMap(PAKFile &out, const ExtractInformation *eI, const int *needList) {
+ int dataEntries = 0;
+ // Count entries in the need list
+ for (const int *n = needList; *n != -1; ++n)
+ ++dataEntries;
+
+ const int mapSize = 2 + dataEntries * (2 + 1 + 4);
+ uint8 *map = new uint8[mapSize];
+ uint8 *dst = map;
+
+ WRITE_BE_UINT16(dst, dataEntries); dst += 2;
+ for (const int *id = needList; *id != -1; ++id) {
+ WRITE_BE_UINT16(dst, *id); dst += 2;
+ const ExtractFilename *fDesc = getFilenameDesc(*id);
+ if (!fDesc)
+ return false;
+ *dst++ = getTypeID(fDesc->type);
+ WRITE_BE_UINT32(dst, getFilename(eI, *id)); dst += 4;
+ }
+
+ char filename[12];
+ if (!getFilename(filename, eI, 0)) {
+ fprintf(stderr, "ERROR: Could not create ID map for game\n");
+ return false;
+ }
+
+ out.removeFile(filename);
+ if (!out.addFile(filename, map, mapSize)) {
+ fprintf(stderr, "ERROR: Could not add ID map \"%s\" to kyra.dat\n", filename);
+ return false;
+ }
+
+ return true;
+}
+
// Uncomment this to get various debug information about the detection table entries.
//#define DEBUG_EXTRACTION_TABLES
diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h
index 93e03d40b6..c247846b93 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/tools/create_kyradat/create_kyradat.h
@@ -27,7 +27,9 @@
// This list has to match orderwise (and thus value wise) the static data list of "engines/kyra/resource.h"!
enum kExtractID {
- k1ForestSeq = 0,
+ kIdMap = 0,
+
+ k1ForestSeq = 1,
k1KallakWritingSeq,
k1KyrandiaLogoSeq,
k1KallakMalcolmSeq,