aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dists/engine-data/kyra.datbin336898 -> 336508 bytes
-rw-r--r--engines/kyra/staticres.cpp186
-rw-r--r--tools/create_kyradat/create_kyradat.cpp234
3 files changed, 232 insertions, 188 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index ed6cad0e9e..aacf17ee23 100644
--- a/dists/engine-data/kyra.dat
+++ b/dists/engine-data/kyra.dat
Binary files differ
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 22cc60c003..d5ebd07dd1 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -45,7 +45,7 @@
namespace Kyra {
-#define RESFILE_VERSION 64
+#define RESFILE_VERSION 65
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -68,75 +68,86 @@ bool checkKyraDat(Common::SeekableReadStream *file) {
return false;
return true;
}
-} // end of anonymous namespace
-
-// used for the KYRA.DAT file which still uses
-// the old flag system, we just convert it, which
-// is less work than to change KYRA.DAT again
-enum {
- GF_FLOPPY = 1 << 0,
- GF_TALKIE = 1 << 1,
- GF_FMTOWNS = 1 << 2,
- GF_DEMO = 1 << 3,
- GF_ENGLISH = 1 << 4,
- GF_FRENCH = 1 << 5,
- GF_GERMAN = 1 << 6,
- GF_SPANISH = 1 << 7,
- GF_ITALIAN = 1 << 8,
- GF_JAPANESE = 1 << 9,
- // other languages here
- GF_LNGUNK = 1 << 16, // also used for multi language in kyra3
- GF_AMIGA = 1 << 17
-};
-
-#define GAME_FLAGS (GF_FLOPPY | GF_TALKIE | GF_DEMO | GF_FMTOWNS | GF_AMIGA)
-#define LANGUAGE_FLAGS (GF_ENGLISH | GF_FRENCH | GF_GERMAN | GF_SPANISH | GF_ITALIAN | GF_JAPANESE | GF_LNGUNK)
-
-uint32 createFeatures(const GameFlags &flags) {
- if (flags.isTalkie && flags.isDemo)
- return GF_TALKIE | GF_DEMO;
- if (flags.isTalkie)
- return GF_TALKIE;
- if (flags.isDemo)
- return GF_DEMO;
- if (flags.platform == Common::kPlatformFMTowns || flags.platform == Common::kPlatformPC98)
- return GF_FMTOWNS;
- if (flags.platform == Common::kPlatformAmiga)
- return GF_AMIGA;
- return GF_FLOPPY;
-}
-
-uint32 createLanguage(const GameFlags &flags) {
- if (flags.lang == Common::EN_ANY)
- return GF_ENGLISH;
- if (flags.lang == Common::DE_DEU)
- return GF_GERMAN;
- if (flags.lang == Common::FR_FRA)
- return GF_FRENCH;
- if (flags.lang == Common::ES_ESP)
- return GF_SPANISH;
- if (flags.lang == Common::IT_ITA)
- return GF_ITALIAN;
- if (flags.lang == Common::JA_JPN)
- return GF_JAPANESE;
- return GF_LNGUNK;
-}
struct LanguageTypes {
- uint32 flags;
+ Common::Language lang;
const char *ext;
};
-static const LanguageTypes languages[] = {
- { GF_ENGLISH, "ENG" }, // this is the default language
- { GF_FRENCH, "FRE" },
- { GF_GERMAN, "GER" },
- { GF_SPANISH, "SPA" },
- { GF_ITALIAN, "ITA" },
- { GF_JAPANESE, "JPN" },
- { 0, 0 }
+const LanguageTypes languages[] = {
+ { Common::EN_ANY, "ENG" },
+ { Common::FR_FRA, "FRE" },
+ { Common::DE_DEU, "GER" },
+ { Common::ES_ESP, "SPA" },
+ { Common::IT_ITA, "ITA" },
+ { Common::JA_JPN, "JPN" },
+ { Common::UNK_LANG, 0 }
};
+struct IndexTable {
+ int type;
+ int value;
+
+ bool operator==(int t) const {
+ return (type == t);
+ }
+};
+
+const IndexTable iGameTable[] = {
+ { GI_KYRA1, 0 },
+ { GI_KYRA2, 1 },
+ { GI_KYRA3, 2 },
+ { GI_LOL, 3 },
+ { -1, -1 }
+};
+
+byte getGameID(const GameFlags &flags) {
+ return Common::find(iGameTable, iGameTable + ARRAYSIZE(iGameTable) - 1, flags.gameID)->value;
+}
+
+/*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 },
+ { -1, -1 }
+};
+
+byte getLanguageID(const GameFlags &flags) {
+ return Common::find(iLanguageTable, iLanguageTable + ARRAYSIZE(iLanguageTable) - 1, flags.lang)->value;
+}*/
+
+const IndexTable iPlatformTable[] = {
+ { Common::kPlatformPC, 0 },
+ { Common::kPlatformAmiga, 1 },
+ { Common::kPlatformFMTowns, 2 },
+ { Common::kPlatformPC98, 3 },
+ { Common::kPlatformMacintosh, 0 }, // HACK: Should be type "4", but as long as we can't extract Macintosh data, we need to use DOS data.
+ { -1, -1 }
+};
+
+byte getPlatformID(const GameFlags &flags) {
+ // HACK: Gross hack to support Kyra2 PC98, till there's data for it in kyra.dat
+ if (flags.gameID == GI_KYRA2 && flags.platform == Common::kPlatformPC98)
+ return 3;
+ return Common::find(iPlatformTable, iPlatformTable + ARRAYSIZE(iPlatformTable) - 1, flags.platform)->value;
+}
+
+byte getSpecialID(const GameFlags &flags) {
+ if (flags.isDemo && flags.isTalkie)
+ return 3;
+ else if (flags.isDemo)
+ return 2;
+ else if (flags.isTalkie)
+ return 1;
+ else
+ return 0;
+}
+
+} // end of anonymous namespace
+
bool StaticResource::loadStaticResourceFile() {
Resource *res = _vm->resource();
@@ -178,30 +189,40 @@ bool StaticResource::loadStaticResourceFile() {
}
bool StaticResource::tryKyraDatLoad() {
- Common::SeekableReadStream *index = getFile("INDEX");
+ Common::SeekableReadStream *index = _vm->resource()->createReadStream("INDEX");
if (!index)
return false;
- if (index->size() != 3*4) {
+ const uint32 version = index->readUint32BE();
+
+ if (version != RESFILE_VERSION) {
delete index;
return false;
}
- uint32 version = index->readUint32BE();
- uint32 gameID = index->readUint32BE();
- uint32 featuresValue = index->readUint32BE();
+ const uint32 includedGames = index->readUint32BE();
- delete index;
- index = 0;
-
- if (version != RESFILE_VERSION)
+ if (includedGames * 2 + 8 != (uint32)index->size()) {
+ delete index;
return false;
+ }
- if (gameID != _vm->game())
- return false;
+ const uint16 gameDef = ((getGameID(_vm->gameFlags()) & 0xF) << 12) |
+ ((getPlatformID(_vm->gameFlags()) & 0xF) << 8) |
+ ((getSpecialID(_vm->gameFlags()) & 0xF) << 4);
- uint32 gameFeatures = createFeatures(_vm->gameFlags());
- if ((featuresValue & GAME_FLAGS) != gameFeatures)
+ bool found = false;
+ for (uint32 i = 0; i < includedGames; ++i) {
+ if (index->readUint16BE() == gameDef) {
+ found = true;
+ break;
+ }
+ }
+
+ delete index;
+ index = 0;
+
+ if (!found)
return false;
// load all tables for now
@@ -705,7 +726,7 @@ const void *StaticResource::getData(int id, int requesttype, int &size) {
bool StaticResource::loadLanguageTable(const char *filename, void *&ptr, int &size) {
static Common::String file;
for (int i = 0; languages[i].ext; ++i) {
- if (languages[i].flags != createLanguage(_vm->gameFlags()))
+ if (languages[i].lang != _vm->gameFlags().lang)
continue;
file = filename;
@@ -714,17 +735,6 @@ bool StaticResource::loadLanguageTable(const char *filename, void *&ptr, int &si
return true;
}
- file = filename;
- file += languages[0].ext;
- if (loadStringTable(file.c_str(), ptr, size)) {
- static bool warned = false;
- if (!warned) {
- warned = true;
- warning("couldn't find specific language table for your version, using English now");
- }
- return true;
- }
-
return false;
}
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index b49472eedc..dbeadb51f0 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -38,10 +38,10 @@
#include <string>
#include <map>
+#include <algorithm>
enum {
- kKyraDatVersion = 64,
- kIndexSize = 12
+ kKyraDatVersion = 65
};
const ExtractFilename extractFilenames[] = {
@@ -353,126 +353,160 @@ const PlatformExtension platformTable[] = {
// index generation
-enum {
- GF_FLOPPY = 1 << 0,
- GF_TALKIE = 1 << 1,
- GF_FMTOWNS = 1 << 2,
- GF_DEMO = 1 << 3,
- GF_ENGLISH = 1 << 4,
- GF_FRENCH = 1 << 5,
- GF_GERMAN = 1 << 6,
- GF_SPANISH = 1 << 7,
- GF_ITALIAN = 1 << 8,
- GF_JAPANESE = 1 << 9,
- // ...
- GF_LNGUNK = 1 << 16,
- GF_AMIGA = 1 << 17
+struct IndexTable {
+ int type;
+ int value;
+
+ bool operator==(int t) const {
+ return (type == t);
+ }
};
-uint32 getFeatures(const Game *g) {
- uint32 features = 0;
-
- if (g->special == kTalkieVersion)
- features |= GF_TALKIE;
- else if (g->special == kDemoVersion)
- features |= GF_DEMO;
- else if (g->special == kTalkieDemoVersion)
- features |= (GF_DEMO | GF_TALKIE);
- else if (g->platform == kPlatformFMTowns || g->platform == kPlatformPC98) // HACK
- features |= GF_FMTOWNS;
- else if (g->platform == kPlatformAmiga)
- features |= GF_AMIGA;
- else
- features |= GF_FLOPPY;
-
- if (g->lang == EN_ANY)
- features |= GF_ENGLISH;
- else if (g->lang == DE_DEU)
- features |= GF_GERMAN;
- else if (g->lang == FR_FRA)
- features |= GF_FRENCH;
- else if (g->lang == ES_ESP)
- features |= GF_SPANISH;
- else if (g->lang == IT_ITA)
- features |= GF_ITALIAN;
- else if (g->lang == JA_JPN)
- features |= GF_JAPANESE;
- else
- features |= GF_LNGUNK;
-
- return features;
+const IndexTable iGameTable[] = {
+ { kKyra1, 0 },
+ { kKyra2, 1 },
+ { kKyra3, 2 },
+ { kLol, 3 },
+ { -1, -1 }
+};
+
+byte getGameID(int game) {
+ return std::find(iGameTable, iGameTable + ARRAYSIZE(iGameTable) - 1, game)->value;
}
-bool updateIndex(byte *dst, const int dstSize, const Game *g) {
- if ((size_t)dstSize < kIndexSize)
- return false;
+/*const IndexTable iLanguageTable[] = {
+ { EN_ANY, 0 },
+ { FR_FRA, 1 },
+ { DE_DEU, 2 },
+ { ES_ESP, 3 },
+ { IT_ITA, 4 },
+ { JA_JPN, 5 },
+ { -1, -1 }
+};
- WRITE_BE_UINT32(dst, kKyraDatVersion); dst += 4;
- WRITE_BE_UINT32(dst, g->game); dst += 4;
- uint32 features = READ_BE_UINT32(dst);
- features |= getFeatures(g);
- WRITE_BE_UINT32(dst, features); dst += 4;
+byte getLanguageID(int lang) {
+ return std::find(iLanguageTable, iLanguageTable + ARRAYSIZE(iLanguageTable) - 1, lang)->value;
+}*/
+
+const IndexTable iPlatformTable[] = {
+ { kPlatformPC, 0 },
+ { kPlatformAmiga, 1 },
+ { kPlatformFMTowns, 2 },
+ { kPlatformPC98, 3 },
+ { kPlatformMacintosh, 4 },
+ { -1, -1 }
+};
- return true;
+byte getPlatformID(int platform) {
+ return std::find(iPlatformTable, iPlatformTable + ARRAYSIZE(iPlatformTable) - 1, platform)->value;
}
-bool checkIndex(const byte *s, const int srcSize) {
- if ((size_t)srcSize < sizeof(uint32))
- return false;
- uint32 version = READ_BE_UINT32(s);
- return (version == kKyraDatVersion);
+const IndexTable iSpecialTable[] = {
+ { kNoSpecial, 0 },
+ { kTalkieVersion, 1 },
+ { kDemoVersion, 2 },
+ { kTalkieDemoVersion, 3 },
+ { -1, -1 }
+};
+
+byte getSpecialID(int special) {
+ return std::find(iSpecialTable, iSpecialTable + ARRAYSIZE(iSpecialTable) - 1, special)->value;
}
-bool updateIndex(PAKFile &out, const Game *g) {
- char filename[32];
- ExtractInformation extractInfo;
- extractInfo.game = g->game;
- extractInfo.lang = -1;
- extractInfo.platform = g->platform;
- extractInfo.special = g->special;
+typedef uint16 GameDef;
- createFilename(filename, &extractInfo, "INDEX");
+GameDef createGameDef(const Game *g) {
+ return ((getGameID(g->game) & 0xF) << 12) |
+ ((getPlatformID(g->platform) & 0xF) << 8) |
+ ((getSpecialID(g->special) & 0xF) << 4);
+}
- byte *index = new byte[kIndexSize];
- assert(index);
- memset(index, 0, kIndexSize);
+struct Index {
+ Index() : version(0), includedGames(0), gameList() {}
+
+ uint32 version;
+ uint32 includedGames;
+
+ typedef std::list<GameDef> GameList;
+ GameList gameList;
+};
+Index parseIndex(const uint8 *data, uint32 size) {
+ Index result;
+
+ if (size < 8)
+ return result;
+
+ result.version = READ_BE_UINT32(data); data += 4;
+ result.includedGames = READ_BE_UINT32(data); data += 4;
+
+ if (result.includedGames * 2 + 8 != size) {
+ result.version = result.includedGames = 0;
+ return result;
+ }
+
+ for (uint32 i = 0; i < result.includedGames; ++i) {
+ GameDef game = READ_BE_UINT16(data); data += 2;
+ result.gameList.push_back(game);
+ }
+
+ return result;
+}
+
+bool updateIndex(PAKFile &out, const Game *g) {
uint32 size = 0;
- const uint8 *data = out.getFileData(filename, &size);
+ const uint8 *data = out.getFileData("INDEX", &size);
+
+ Index index;
if (data)
- memcpy(index, data, size);
+ index = parseIndex(data, size);
- if (!updateIndex(index, kIndexSize, g)) {
- delete[] index;
- return false;
+ GameDef gameDef = createGameDef(g);
+ if (index.version == kKyraDatVersion) {
+ if (std::find(index.gameList.begin(), index.gameList.end(), gameDef) == index.gameList.end()) {
+ ++index.includedGames;
+ index.gameList.push_back(gameDef);
+ }
+ } else {
+ index.version = kKyraDatVersion;
+ index.includedGames = 1;
+ index.gameList.push_back(gameDef);
+ }
+
+ const uint32 indexBufferSize = 8 + index.includedGames * 2;
+ uint8 *indexBuffer = new uint8[indexBufferSize];
+ assert(indexBuffer);
+ uint8 *dst = indexBuffer;
+ WRITE_BE_UINT32(dst, index.version); dst += 4;
+ WRITE_BE_UINT32(dst, index.includedGames); dst += 4;
+ for (Index::GameList::const_iterator i = index.gameList.begin(); i != index.gameList.end(); ++i) {
+ WRITE_BE_UINT16(dst, *i); dst += 2;
}
- out.removeFile(filename);
- if (!out.addFile(filename, index, kIndexSize)) {
- fprintf(stderr, "ERROR: couldn't update %s file\n", filename);
- delete[] index;
+ out.removeFile("INDEX");
+ if (!out.addFile("INDEX", indexBuffer, indexBufferSize)) {
+ fprintf(stderr, "ERROR: couldn't update kyra.dat INDEX\n");
+ delete[] indexBuffer;
return false;
}
return true;
}
-bool checkIndex(PAKFile &out, const Game *g) {
- char filename[32];
- ExtractInformation extractInfo;
- extractInfo.game = g->game;
- extractInfo.lang = -1;
- extractInfo.platform = g->platform;
- extractInfo.special = g->special;
-
- createFilename(filename, &extractInfo, "INDEX");
-
+bool checkIndex(PAKFile &file) {
uint32 size = 0;
- const uint8 *data = out.getFileData(filename, &size);
+ const uint8 *data = file.getFileData("INDEX", &size);
if (!data)
- return true;
+ return false;
- return checkIndex(data, size);
+ Index index = parseIndex(data, size);
+
+ if (index.version != kKyraDatVersion)
+ return false;
+ if (index.includedGames * 2 + 8 != size)
+ return false;
+
+ return true;
}
// main processing
@@ -548,6 +582,11 @@ int main(int argc, char *argv[]) {
PAKFile out;
out.loadFile(argv[1], false);
+ // When the output file is no valid kyra.dat file, we will delete
+ // all the output.
+ if (!checkIndex(out))
+ out.clearFile();
+
MD5Map inputFiles = createMD5Sums(argc - 2, &argv[2]);
GameMap games = createGameMap(inputFiles);
@@ -1134,11 +1173,6 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
extractInfo.platform = g->platform;
extractInfo.special = g->special;
- if (!checkIndex(out, g)) {
- fprintf(stderr, "ERROR: corrupted INDEX file\n");
- return false;
- }
-
Search search(data, size);
IdMap ids;