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; }
uint32 getFilename(const Game *g, const int id) { const ExtractFilename *fDesc = getFilenameDesc(id); if (!fDesc) return 0; return getFilename(g->game, g->platform, g->special, g->lang, fDesc); }
void outputAllResources(PAKFile &out) { char filename[128]; for (const ResourceProvider *resource = obtainResourceProviders(); resource->id != kMaxResIDs; ++resource) { const ExtractFilename *desc = getFilenameDesc(resource->id); snprintf(filename, sizeof(filename), "%08X", getFilename(resource, desc)); writeResource(out, filename, (ResTypes)desc->type, resource->provider); } }
uint32 getFilename(const ExtractInformation *info, const int id) { const ExtractFilename *fDesc = getFilenameDesc(id); 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); }
bool createIDMap(PAKFile &out, const Game *g, const int *needList) { int dataEntries = 0; // Count entries in the need list and check whether the resources are // present for (const int *n = needList; *n != -1; ++n) { char filename[12]; if (!getFilename(filename, g, *n) || !out.getFileList()->findEntry(filename)) { fprintf(stderr, "ERROR: Could not find need %d for game %04X", *n, createGameDef(g)); return false; } ++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) { delete[] map; return false; } *dst++ = fDesc->type; WRITE_BE_UINT32(dst, getFilename(g, *id)); dst += 4; } char filename[12]; if (!getFilename(filename, g, 0)) { fprintf(stderr, "ERROR: Could not create ID map for game\n"); delete[] map; return false; } if (!out.addFile(filename, map, mapSize)) { fprintf(stderr, "ERROR: Could not add ID map \"%s\" to kyra.dat\n", filename); delete[] map; return false; } return true; }
bool isLangSpecific(const int id) { const ExtractFilename *desc = getFilenameDesc(id); if (!desc) return false; return desc->langSpecific; }
bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) { char filename[128]; Search search(data, size); ExtractMap ids; if (!getExtractionData(g, search, ids)) return false; const int *needList = getNeedList(g); if (!needList) { fprintf(stderr, "ERROR: No entry need list available\n"); return false; } ExtractInformation extractInfo; extractInfo.game = g->game; extractInfo.platform = g->platform; extractInfo.special = g->special; 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); if (!fDesc) { fprintf(stderr, "ERROR: couldn't find file description for id %d/%s\n", id, getIdString(id)); return false; } filename[0] = 0; if (!getFilename(filename, &extractInfo, id)) { fprintf(stderr, "ERROR: couldn't get filename for id %d/%s\n", id, getIdString(id)); return false; } const ExtractType *tDesc = findExtractType(fDesc->type); if (!tDesc) { fprintf(stderr, "ERROR: couldn't find type description for id %d/%s (%d)\n", id, getIdString(id), fDesc->type); return false; } PAKFile::cFileList *list = out.getFileList(); if (list && list->findEntry(filename) != 0) continue; if (!tDesc->extract(out, &extractInfo, data + i->second.offset, i->second.desc.hint.size, filename, id)) { fprintf(stderr, "ERROR: couldn't extract id %d/%s\n", id, getIdString(id)); return false; } } for (int i = 0; i < 3; ++i) { if (g->lang[i] == -1) 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; } } return true; }