scummvm/devtools/create_kyradat/create_kyradat.cpp

941 lines
33 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
// HACK to allow building with the SDL backend on MinGW
// see bug #1800764 "TOOLS: MinGW tools building broken"
#ifdef main
#undef main
#endif // main
#include "create_kyradat.h"
#include "resources.h"
#include "types.h"
#include "pak.h"
#include "md5.h"
#include "common/language.h"
#include "common/platform.h"
#include <vector>
#include <string>
#include <algorithm>
enum {
kKyraDatVersion = 86
};
const ExtractFilename extractFilenames[] = {
// GENERIC ID MAP
{ kIdMap, -1, true },
// INTRO / OUTRO sequences
{ k1ForestSeq, kRawData, false },
{ k1KallakWritingSeq, kRawData, false },
{ k1KyrandiaLogoSeq, kRawData, false },
{ k1KallakMalcolmSeq, kRawData, false },
{ k1MalcolmTreeSeq, kRawData, false },
{ k1WestwoodLogoSeq, kRawData, false },
{ k1Demo1Seq, kRawData, false },
{ k1Demo2Seq, kRawData, false },
{ k1Demo3Seq, kRawData, false },
{ k1Demo4Seq, kRawData, false },
{ k1OutroReunionSeq, kRawData, false },
// INTRO / OUTRO strings
{ k1IntroCPSStrings, kStringList, false },
{ k1IntroCOLStrings, kStringList, false },
{ k1IntroWSAStrings, kStringList, false },
{ k1IntroStrings, kStringList, true },
{ k1OutroHomeString, kStringList, true },
// INGAME strings
{ k1ItemNames, kStringList, true },
{ k1TakenStrings, kStringList, true },
{ k1PlacedStrings, kStringList, true },
{ k1DroppedStrings, kStringList, true },
{ k1NoDropStrings, kStringList, true },
{ k1PutDownString, kStringList, true },
{ k1WaitAmuletString, kStringList, true },
{ k1BlackJewelString, kStringList, true },
{ k1PoisonGoneString, kStringList, true },
{ k1HealingTipString, kStringList, true },
{ k1ThePoisonStrings, kStringList, true },
{ k1FluteStrings, kStringList, true },
{ k1WispJewelStrings, kStringList, true },
{ k1MagicJewelStrings, kStringList, true },
{ k1FlaskFullString, kStringList, true },
{ k1FullFlaskString, kStringList, true },
{ k1VeryCleverString, kStringList, true },
{ k1NewGameString, kStringList, true },
// GUI strings table
{ k1GUIStrings, kStringList, true },
{ k1ConfigStrings, kStringList, true },
// ROOM table/filenames
{ k1RoomList, kRoomList, false },
{ k1RoomFilenames, kStringList, false },
// SHAPE tables
{ k1DefaultShapes, kShapeList, false },
{ k1Healing1Shapes, kShapeList, false },
{ k1Healing2Shapes, kShapeList, false },
{ k1PoisonDeathShapes, kShapeList, false },
{ k1FluteShapes, kShapeList, false },
{ k1Winter1Shapes, kShapeList, false },
{ k1Winter2Shapes, kShapeList, false },
{ k1Winter3Shapes, kShapeList, false },
{ k1DrinkShapes, kShapeList, false },
{ k1WispShapes, kShapeList, false },
{ k1MagicAnimShapes, kShapeList, false },
{ k1BranStoneShapes, kShapeList, false },
// IMAGE filename table
{ k1CharacterImageFilenames, kStringList, false },
// AUDIO filename table
{ k1AudioTracks, kStringList, false },
{ k1AudioTracks2, kStringList, false },
{ k1AudioTracksIntro, kStringList, false },
// AMULET anim
{ k1AmuleteAnimSeq, kRawData, false },
// PALETTE table
{ k1SpecialPalette1, kRawData, false },
{ k1SpecialPalette2, kRawData, false },
{ k1SpecialPalette3, kRawData, false },
{ k1SpecialPalette4, kRawData, false },
{ k1SpecialPalette5, kRawData, false },
{ k1SpecialPalette6, kRawData, false },
{ k1SpecialPalette7, kRawData, false },
{ k1SpecialPalette8, kRawData, false },
{ k1SpecialPalette9, kRawData, false },
{ k1SpecialPalette10, kRawData, false },
{ k1SpecialPalette11, kRawData, false },
{ k1SpecialPalette12, kRawData, false },
{ k1SpecialPalette13, kRawData, false },
{ k1SpecialPalette14, kRawData, false },
{ k1SpecialPalette15, kRawData, false },
{ k1SpecialPalette16, kRawData, false },
{ k1SpecialPalette17, kRawData, false },
{ k1SpecialPalette18, kRawData, false },
{ k1SpecialPalette19, kRawData, false },
{ k1SpecialPalette20, kRawData, false },
{ k1SpecialPalette21, kRawData, false },
{ k1SpecialPalette22, kRawData, false },
{ k1SpecialPalette23, kRawData, false },
{ k1SpecialPalette24, kRawData, false },
{ k1SpecialPalette25, kRawData, false },
{ k1SpecialPalette26, kRawData, false },
{ k1SpecialPalette27, kRawData, false },
{ k1SpecialPalette28, kRawData, false },
{ k1SpecialPalette29, kRawData, false },
{ k1SpecialPalette30, kRawData, false },
{ k1SpecialPalette31, kRawData, false },
{ k1SpecialPalette32, kRawData, false },
{ k1SpecialPalette33, kRawData, false },
// CREDITS (used in FM-TOWNS and AMIGA)
{ k1CreditsStrings, kRawData, true },
// FM-TOWNS specific
{ k1TownsMusicFadeTable, kRawData, false },
{ k1TownsSFXwdTable, kRawData, false },
{ k1TownsSFXbtTable, kRawData, false },
{ k1TownsCDATable, kRawData, false },
// PC98 specific
{ k1PC98StoryStrings, kStringList, true },
{ k1PC98IntroSfx, kRawData, false },
// AMIGA specific
{ k1AmigaIntroSFXTable, kAmigaSfxTable, false },
{ k1AmigaGameSFXTable, kAmigaSfxTable, false },
// HAND OF FATE
// Sequence Player
{ k2SeqplayPakFiles, kStringList, false },
{ k2SeqplayCredits, kRawData, false },
{ k2SeqplayCreditsSpecial, kStringList, false },
{ k2SeqplayStrings, kStringList, true },
{ k2SeqplaySfxFiles, kStringList, false },
{ k2SeqplayTlkFiles, kStringList, true },
{ k2SeqplaySeqData, k2SeqData, false },
{ k2SeqplayIntroTracks, kStringList, false },
{ k2SeqplayFinaleTracks, kStringList, false },
{ k2SeqplayIntroCDA, kRawData, false },
{ k2SeqplayFinaleCDA, kRawData, false },
{ k2SeqplayShapeAnimData, k2SeqItemAnimData, false },
// Ingame
{ k2IngamePakFiles, kStringList, false },
{ k2IngameSfxFiles, kStringList, false },
{ k2IngameSfxIndex, kRawData, false },
{ k2IngameTracks, kStringList, false },
{ k2IngameCDA, kRawData, false },
{ k2IngameTalkObjIndex, kRawData, false },
{ k2IngameTimJpStrings, kStringList, false },
{ k2IngameShapeAnimData, k2ItemAnimDefinition, false },
{ k2IngameTlkDemoStrings, kStringList, true },
// MALCOLM'S REVENGE
{ k3MainMenuStrings, kStringList, false },
{ k3MusicFiles, kStringList, false },
{ k3ScoreTable, kRawData, false },
{ k3SfxFiles, kStringList, false },
{ k3SfxMap, kRawData, false },
{ k3ItemAnimData, k2ItemAnimDefinition, false },
{ k3ItemMagicTable, kRawData, false },
{ k3ItemStringMap, kRawData, false },
// EYE OF THE BEHOLDER COMMON
{ kEoBBaseChargenStrings1, kStringList, true },
{ kEoBBaseChargenStrings2, kStringList, true },
{ kEoBBaseChargenStartLevels, kRawData, false },
{ kEoBBaseChargenStatStrings, kStringList, true},
{ kEoBBaseChargenRaceSexStrings, kStringList, true },
{ kEoBBaseChargenClassStrings, kStringList, true },
{ kEoBBaseChargenAlignmentStrings, kStringList, true },
{ kEoBBaseChargenEnterGameStrings, kStringList, true },
{ kEoBBaseChargenClassMinStats, kRawData, false },
{ kEoBBaseChargenRaceMinStats, kRawData, false },
{ kEoBBaseChargenRaceMaxStats, kRawDataBe16, false },
{ kEoBBaseSaveThrowTable1, kRawData, false },
{ kEoBBaseSaveThrowTable2, kRawData, false },
{ kEoBBaseSaveThrowTable3, kRawData, false },
{ kEoBBaseSaveThrowTable4, kRawData, false },
{ kEoBBaseSaveThrwLvlIndex, kRawData, false },
{ kEoBBaseSaveThrwModDiv, kRawData, false },
{ kEoBBaseSaveThrwModExt, kRawData, false },
{ kEoBBasePryDoorStrings, kStringList, true },
{ kEoBBaseWarningStrings, kStringList, true },
{ kEoBBaseItemSuffixStringsRings, kStringList, true },
{ kEoBBaseItemSuffixStringsPotions, kStringList, true },
{ kEoBBaseItemSuffixStringsWands, kStringList, true },
{ kEoBBaseRipItemStrings, kStringList, true },
{ kEoBBaseCursedString, kStringList, true },
{ kEoBBaseEnchantedString, kStringList, false },
{ kEoBBaseMagicObjectStrings, kStringList, true },
{ kEoBBaseMagicObjectString5, kStringList, true },
{ kEoBBasePatternSuffix, kStringList, true },
{ kEoBBasePatternGrFix1, kStringList, true },
{ kEoBBasePatternGrFix2, kStringList, true },
{ kEoBBaseValidateArmorString, kStringList, true },
{ kEoBBaseValidateCursedString, kStringList, true },
{ kEoBBaseValidateNoDropString, kStringList, true },
{ kEoBBasePotionStrings, kStringList, true },
{ kEoBBaseWandStrings, kStringList, true },
{ kEoBBaseItemMisuseStrings, kStringList, true },
{ kEoBBaseTakenStrings, kStringList, true },
{ kEoBBasePotionEffectStrings, kStringList, true },
{ kEoBBaseYesNoStrings, kStringList, true },
{ kRpgCommonMoreStrings, kStringList, true },
{ kEoBBaseNpcMaxStrings, kStringList, true },
{ kEoBBaseOkStrings, kStringList, true },
{ kEoBBaseNpcJoinStrings, kStringList, true },
{ kEoBBaseCancelStrings, kStringList, true },
{ kEoBBaseAbortStrings, kStringList, true },
{ kEoBBaseMenuStringsMain, kStringList, true },
{ kEoBBaseMenuStringsSaveLoad, kStringList, true },
{ kEoBBaseMenuStringsOnOff, kStringList, true },
{ kEoBBaseMenuStringsSpells, kStringList, true },
{ kEoBBaseMenuStringsRest, kStringList, true },
{ kEoBBaseMenuStringsDrop, kStringList, true },
{ kEoBBaseMenuStringsExit, kStringList, true },
{ kEoBBaseMenuStringsStarve, kStringList, true },
{ kEoBBaseMenuStringsScribe, kStringList, true },
{ kEoBBaseMenuStringsDrop2, kStringList, true },
{ kEoBBaseMenuStringsHead, kStringList, true },
{ kEoBBaseMenuStringsPoison, kStringList, true },
{ kEoBBaseMenuStringsMgc, kStringList, true },
{ kEoBBaseMenuStringsPrefs, kStringList, true },
{ kEoBBaseMenuStringsRest2, kStringList, true },
{ kEoBBaseMenuStringsRest3, kStringList, true },
{ kEoBBaseMenuStringsRest4, kStringList, true },
{ kEoBBaseMenuStringsDefeat, kStringList, true },
{ kEoBBaseMenuStringsTransfer, kStringList, true },
{ kEoBBaseMenuStringsSpec, kStringList, true },
{ kEoBBaseMenuStringsSpellNo, kStringList, false },
{ kEoBBaseMenuYesNoStrings, kStringList, true },
{ kEoBBaseSpellLevelsMage, kRawData, false },
{ kEoBBaseSpellLevelsCleric, kRawData, false },
{ kEoBBaseNumSpellsCleric, kRawData, false },
{ kEoBBaseNumSpellsWisAdj, kRawData, false },
{ kEoBBaseNumSpellsPal, kRawData, false },
{ kEoBBaseNumSpellsMage, kRawData, false },
{ kEoBBaseCharGuiStringsHp, kStringList, true },
{ kEoBBaseCharGuiStringsWp1, kStringList, true },
{ kEoBBaseCharGuiStringsWp2, kStringList, true },
{ kEoBBaseCharGuiStringsWr, kStringList, true },
{ kEoBBaseCharGuiStringsSt1, kStringList, true },
{ kEoBBaseCharGuiStringsSt2, kStringList, true },
{ kEoBBaseCharGuiStringsIn, kStringList, true },
{ kEoBBaseCharStatusStrings7, kStringList, true },
{ kEoBBaseCharStatusStrings81, kStringList, true },
{ kEoBBaseCharStatusStrings82, kStringList, true },
{ kEoBBaseCharStatusStrings9, kStringList, true },
{ kEoBBaseCharStatusStrings12, kStringList, true },
{ kEoBBaseCharStatusStrings131, kStringList, true },
{ kEoBBaseCharStatusStrings132, kStringList, true },
{ kEoBBaseLevelGainStrings, kStringList, true },
{ kEoBBaseExperienceTable0, kRawDataBe32, false },
{ kEoBBaseExperienceTable1, kRawDataBe32, false },
{ kEoBBaseExperienceTable2, kRawDataBe32, false },
{ kEoBBaseExperienceTable3, kRawDataBe32, false },
{ kEoBBaseExperienceTable4, kRawDataBe32, false },
{ kEoBBaseWllFlagPreset, kRawData, false },
{ kEoBBaseDscShapeCoords, kRawDataBe16, false },
{ kEoBBaseDscDoorScaleOffs, kRawData, false },
{ kEoBBaseDscDoorScaleMult1, kRawData, false },
{ kEoBBaseDscDoorScaleMult2, kRawData, false },
{ kEoBBaseDscDoorScaleMult3, kRawData, false },
{ kEoBBaseDscDoorScaleMult4, kRawData, false },
{ kEoBBaseDscDoorScaleMult5, kRawData, false },
{ kEoBBaseDscDoorScaleMult6, kRawData, false },
{ kEoBBaseDscDoorType5Offs, kRawData, false },
{ kEoBBaseDscDoorXE, kRawData, false },
{ kEoBBaseDscDoorY1, kRawData, false },
{ kEoBBaseDscDoorY3, kRawData, false },
{ kEoBBaseDscDoorY4, kRawData, false },
{ kEoBBaseDscDoorY5, kRawData, false },
{ kEoBBaseDscDoorY6, kRawData, false },
{ kEoBBaseDscDoorY7, kRawData, false },
{ kEoBBaseDscDoorCoordsExt, kRawDataBe16, false },
{ kEoBBaseDscItemPosIndex, kRawData, false },
{ kEoBBaseDscItemShpX, kRawDataBe16, false },
{ kEoBBaseDscItemScaleIndex, kRawData, false },
{ kEoBBaseDscItemTileIndex, kRawData, false },
{ kEoBBaseDscItemShapeMap, kRawData, false },
{ kEoBBaseDscTelptrShpCoords, kRawData, false },
{ kEoBBasePortalSeqData, kRawData, false },
{ kEoBBaseManDef, kRawData, true },
{ kEoBBaseManWord, kStringList, true },
{ kEoBBaseManPrompt, kStringList, true },
{ kEoBBaseDscMonsterFrmOffsTbl1, kRawData, false },
{ kEoBBaseDscMonsterFrmOffsTbl2, kRawData, false },
{ kEoBBaseInvSlotX, kRawDataBe16, false },
{ kEoBBaseInvSlotY, kRawData, false },
{ kEoBBaseSlotValidationFlags, kRawDataBe16, false },
{ kEoBBaseProjectileWeaponTypes, kRawData, false },
{ kEoBBaseWandTypes, kRawData, false },
{ kEoBBaseDrawObjPosIndex, kRawData, false },
{ kEoBBaseFlightObjFlipIndex, kRawData, false },
{ kEoBBaseFlightObjShpMap, kRawData, false },
{ kEoBBaseFlightObjSclIndex, kRawData, false },
{ kEoBBaseBookNumbers, kStringList, true },
{ kEoBBaseMageSpellsList, kStringList, true },
{ kEoBBaseClericSpellsList, kStringList, true },
{ kEoBBaseSpellNames, kStringList, true },
{ kEoBBaseMagicStrings1, kStringList, true },
{ kEoBBaseMagicStrings2, kStringList, true },
{ kEoBBaseMagicStrings3, kStringList, true },
{ kEoBBaseMagicStrings4, kStringList, true },
{ kEoBBaseMagicStrings6, kStringList, true },
{ kEoBBaseMagicStrings7, kStringList, true },
{ kEoBBaseMagicStrings8, kStringList, true },
{ kEoBBaseExpObjectTlMode, kRawData, false },
{ kEoBBaseExpObjectTblIndex, kRawData, false },
{ kEoBBaseExpObjectShpStart, kRawData, false },
{ kEoBBaseExpObjectTbl1, kRawData, false },
{ kEoBBaseExpObjectTbl2, kRawData, false },
{ kEoBBaseExpObjectTbl3, kRawData, false },
{ kEoBBaseExpObjectY, kRawData, false },
{ kEoBBaseSparkDefSteps, kRawData, false },
{ kEoBBaseSparkDefSubSteps, kRawData, false },
{ kEoBBaseSparkDefShift, kRawData, false },
{ kEoBBaseSparkDefAdd, kRawData, false },
{ kEoBBaseSparkDefX, kRawData, false },
{ kEoBBaseSparkDefY, kRawData, false },
{ kEoBBaseSparkOfFlags1, kRawDataBe32, false },
{ kEoBBaseSparkOfFlags2, kRawDataBe32, false },
{ kEoBBaseSparkOfShift, kRawData, false },
{ kEoBBaseSparkOfX, kRawData, false },
{ kEoBBaseSparkOfY, kRawData, false },
{ kEoBBaseSpellProperties, kRawData, false },
{ kEoBBaseMagicFlightProps, kRawData, false },
{ kEoBBaseTurnUndeadEffect, kRawData, false },
{ kEoBBaseBurningHandsDest, kRawData, false },
{ kEoBBaseConeOfColdDest1, kRawData, false },
{ kEoBBaseConeOfColdDest2, kRawData, false },
{ kEoBBaseConeOfColdDest3, kRawData, false },
{ kEoBBaseConeOfColdDest4, kRawData, false },
{ kEoBBaseConeOfColdGfxTbl, kRawData, false },
// EYE OF THE BEHOLDER I
{ kEoB1MainMenuStrings, kStringList, true },
{ kEoB1BonusStrings, kStringList, true },
{ kEoB1IntroFilesOpening, kStringList, false },
{ kEoB1IntroFilesTower, kStringList, false },
{ kEoB1IntroFilesOrb, kStringList, false },
{ kEoB1IntroFilesWdEntry, kStringList, false },
{ kEoB1IntroFilesKing, kStringList, false },
{ kEoB1IntroFilesHands, kStringList, false },
{ kEoB1IntroFilesWdExit, kStringList, false },
{ kEoB1IntroFilesTunnel, kStringList, false },
{ kEoB1IntroOpeningFrmDelay, kRawData, false },
{ kEoB1IntroWdEncodeX, kRawData, false },
{ kEoB1IntroWdEncodeY, kRawData, false },
{ kEoB1IntroWdEncodeWH, kRawData, false },
{ kEoB1IntroWdDsX, kRawDataBe16, false },
{ kEoB1IntroWdDsY, kRawData, false },
{ kEoB1IntroTvlX1, kRawData, false },
{ kEoB1IntroTvlY1, kRawData, false },
{ kEoB1IntroTvlX2, kRawData, false },
{ kEoB1IntroTvlY2, kRawData, false },
{ kEoB1IntroTvlW, kRawData, false },
{ kEoB1IntroTvlH, kRawData, false },
{ kEoB1DoorShapeDefs, kRawData, false },
{ kEoB1DoorSwitchShapeDefs, kRawData, false },
{ kEoB1DoorSwitchCoords, kRawData, false },
{ kEoB1MonsterProperties, kRawData, false },
{ kEoB1EnemyMageSpellList, kRawData, false },
{ kEoB1EnemyMageSfx, kRawData, false },
{ kEoB1BeholderSpellList, kRawData, false },
{ kEoB1BeholderSfx, kRawData, false },
{ kEoB1TurnUndeadString, kStringList, true },
{ kEoB1CgaMappingDefault, kRawData, false },
{ kEoB1CgaMappingAlt, kRawData, false },
{ kEoB1CgaMappingInv, kRawData, false },
{ kEoB1CgaMappingItemsL, kRawData, false },
{ kEoB1CgaMappingItemsS, kRawData, false },
{ kEoB1CgaMappingThrown, kRawData, false },
{ kEoB1CgaMappingIcons, kRawData, false },
{ kEoB1CgaMappingDeco, kRawData, false },
{ kEoB1CgaLevelMappingIndex, kRawData, false },
{ kEoB1CgaMappingLevel0, kRawData, false },
{ kEoB1CgaMappingLevel1, kRawData, false },
{ kEoB1CgaMappingLevel2, kRawData, false },
{ kEoB1CgaMappingLevel3, kRawData, false },
{ kEoB1CgaMappingLevel4, kRawData, false },
{ kEoB1NpcShpData, kRawData, false },
{ kEoB1NpcSubShpIndex1, kRawData, false },
{ kEoB1NpcSubShpIndex2, kRawData, false },
{ kEoB1NpcSubShpY, kRawData, false },
{ kEoB1Npc0Strings, kStringList, true },
{ kEoB1Npc11Strings, kStringList, true },
{ kEoB1Npc12Strings, kStringList, true },
{ kEoB1Npc21Strings, kStringList, true },
{ kEoB1Npc22Strings, kStringList, true },
{ kEoB1Npc31Strings, kStringList, true },
{ kEoB1Npc32Strings, kStringList, true },
{ kEoB1Npc4Strings, kStringList, true },
{ kEoB1Npc5Strings, kStringList, true },
{ kEoB1Npc6Strings, kStringList, true },
{ kEoB1Npc7Strings, kStringList, true },
// EYE OF THE BEHOLDER II
{ kEoB2MainMenuStrings, kStringList, true },
{ kEoB2TransferPortraitFrames, kRawDataBe16, false },
{ kEoB2TransferConvertTable, kRawData, false },
{ kEoB2TransferItemTable, kRawData, false },
{ kEoB2TransferExpTable, kRawDataBe32, false },
{ kEoB2TransferStrings1, kStringList, true },
{ kEoB2TransferStrings2, kStringList, true },
{ kEoB2TransferLabels, kStringList, true },
{ kEoB2IntroStrings, kStringList, true },
{ kEoB2IntroCPSFiles, kStringList, true },
{ kEoB2IntroAnimData00, kEoB2SequenceData, false },
{ kEoB2IntroAnimData01, kEoB2SequenceData, false },
{ kEoB2IntroAnimData02, kEoB2SequenceData, false },
{ kEoB2IntroAnimData03, kEoB2SequenceData, false },
{ kEoB2IntroAnimData04, kEoB2SequenceData, false },
{ kEoB2IntroAnimData05, kEoB2SequenceData, false },
{ kEoB2IntroAnimData06, kEoB2SequenceData, false },
{ kEoB2IntroAnimData07, kEoB2SequenceData, false },
{ kEoB2IntroAnimData08, kEoB2SequenceData, false },
{ kEoB2IntroAnimData09, kEoB2SequenceData, false },
{ kEoB2IntroAnimData10, kEoB2SequenceData, false },
{ kEoB2IntroAnimData11, kEoB2SequenceData, false },
{ kEoB2IntroAnimData12, kEoB2SequenceData, false },
{ kEoB2IntroAnimData13, kEoB2SequenceData, false },
{ kEoB2IntroAnimData14, kEoB2SequenceData, false },
{ kEoB2IntroAnimData15, kEoB2SequenceData, false },
{ kEoB2IntroAnimData16, kEoB2SequenceData, false },
{ kEoB2IntroAnimData17, kEoB2SequenceData, false },
{ kEoB2IntroAnimData18, kEoB2SequenceData, false },
{ kEoB2IntroAnimData19, kEoB2SequenceData, false },
{ kEoB2IntroAnimData20, kEoB2SequenceData, false },
{ kEoB2IntroAnimData21, kEoB2SequenceData, false },
{ kEoB2IntroAnimData22, kEoB2SequenceData, false },
{ kEoB2IntroAnimData23, kEoB2SequenceData, false },
{ kEoB2IntroAnimData24, kEoB2SequenceData, false },
{ kEoB2IntroAnimData25, kEoB2SequenceData, false },
{ kEoB2IntroAnimData26, kEoB2SequenceData, false },
{ kEoB2IntroAnimData27, kEoB2SequenceData, false },
{ kEoB2IntroAnimData28, kEoB2SequenceData, false },
{ kEoB2IntroAnimData29, kEoB2SequenceData, false },
{ kEoB2IntroAnimData30, kEoB2SequenceData, false },
{ kEoB2IntroAnimData31, kEoB2SequenceData, false },
{ kEoB2IntroAnimData32, kEoB2SequenceData, false },
{ kEoB2IntroAnimData33, kEoB2SequenceData, false },
{ kEoB2IntroAnimData34, kEoB2SequenceData, false },
{ kEoB2IntroAnimData35, kEoB2SequenceData, false },
{ kEoB2IntroAnimData36, kEoB2SequenceData, false },
{ kEoB2IntroAnimData37, kEoB2SequenceData, false },
{ kEoB2IntroAnimData38, kEoB2SequenceData, false },
{ kEoB2IntroAnimData39, kEoB2SequenceData, false },
{ kEoB2IntroAnimData40, kEoB2SequenceData, false },
{ kEoB2IntroAnimData41, kEoB2SequenceData, false },
{ kEoB2IntroAnimData42, kEoB2SequenceData, false },
{ kEoB2IntroAnimData43, kEoB2SequenceData, false },
{ kEoB2IntroShapes00, kEoB2ShapeData, false },
{ kEoB2IntroShapes01, kEoB2ShapeData, false },
{ kEoB2IntroShapes04, kEoB2ShapeData, false },
{ kEoB2IntroShapes07, kEoB2ShapeData, false },
{ kEoB2FinaleStrings, kStringList, true },
{ kEoB2CreditsData, kRawData, true },
{ kEoB2FinaleCPSFiles, kStringList, true },
{ kEoB2FinaleAnimData00, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData01, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData02, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData03, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData04, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData05, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData06, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData07, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData08, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData09, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData10, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData11, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData12, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData13, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData14, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData15, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData16, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData17, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData18, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData19, kEoB2SequenceData, false },
{ kEoB2FinaleAnimData20, kEoB2SequenceData, false },
{ kEoB2FinaleShapes00, kEoB2ShapeData, false },
{ kEoB2FinaleShapes03, kEoB2ShapeData, false },
{ kEoB2FinaleShapes07, kEoB2ShapeData, false },
{ kEoB2FinaleShapes09, kEoB2ShapeData, false },
{ kEoB2FinaleShapes10, kEoB2ShapeData, false },
{ kEoB2NpcShapeData, kRawData, false },
{ kEoBBaseClassModifierFlags, kRawData, false },
{ kEoBBaseMonsterStepTable01, kRawData, false },
{ kEoBBaseMonsterStepTable02, kRawData, false },
{ kEoBBaseMonsterStepTable1, kRawData, false },
{ kEoBBaseMonsterStepTable2, kRawData, false },
{ kEoBBaseMonsterStepTable3, kRawData, false },
{ kEoBBaseMonsterCloseAttPosTable1, kRawData, false },
{ kEoBBaseMonsterCloseAttPosTable21, kRawData, false },
{ kEoBBaseMonsterCloseAttPosTable22, kRawData, false },
{ kEoBBaseMonsterCloseAttUnkTable, kRawData, false },
{ kEoBBaseMonsterCloseAttChkTable1, kRawData, false },
{ kEoBBaseMonsterCloseAttChkTable2, kRawData, false },
{ kEoBBaseMonsterCloseAttDstTable1, kRawData, false },
{ kEoBBaseMonsterCloseAttDstTable2, kRawData, false },
{ kEoBBaseMonsterProximityTable, kRawData, false },
{ kEoBBaseFindBlockMonstersTable, kRawData, false },
{ kEoBBaseMonsterDirChangeTable, kRawData, false },
{ kEoBBaseMonsterDistAttStrings, kStringList, true },
{ kEoBBaseEncodeMonsterDefs, kRawDataBe16, false },
{ kEoBBaseNpcPresets, kEoBNpcData, false },
{ kEoB2Npc1Strings, kStringList, true },
{ kEoB2Npc2Strings, kStringList, true },
{ kEoB2MonsterDustStrings, kStringList, true },
{ kEoB2DreamSteps, kRawData, false },
{ kEoB2KheldranStrings, kStringList, true },
{ kEoB2HornStrings, kStringList, true },
{ kEoB2HornSounds, kRawData, false },
{ kEoB2WallOfForceDsX, kRawDataBe16, false },
{ kEoB2WallOfForceDsY, kRawData, false },
{ kEoB2WallOfForceNumW, kRawData, false },
{ kEoB2WallOfForceNumH, kRawData, false },
{ kEoB2WallOfForceShpId, kRawData, false },
// LANDS OF LORE
// Ingame
{ kLoLIngamePakFiles, kStringList, false },
{ kLoLCharacterDefs, kLoLCharData, true },
{ kLoLIngameSfxFiles, kStringList, false },
{ kLoLIngameSfxIndex, kRawData, false },
{ kLoLMusicTrackMap, kRawData, false },
{ kLoLIngameGMSfxIndex, kRawData, false },
{ kLoLIngameMT32SfxIndex, kRawData, false },
{ kLoLIngamePcSpkSfxIndex, kRawData, false },
{ kLoLSpellProperties, kLoLSpellData, false },
{ kLoLGameShapeMap, kRawData, false },
{ kLoLSceneItemOffs, kRawData, false },
{ kLoLCharInvIndex, kRawData, false },
{ kLoLCharInvDefs, kRawData, false },
{ kLoLCharDefsMan, kRawDataBe16, false },
{ kLoLCharDefsWoman, kRawDataBe16, false },
{ kLoLCharDefsKieran, kRawDataBe16, false },
{ kLoLCharDefsAkshel, kRawDataBe16, false },
{ kLoLExpRequirements, kRawDataBe32, false },
{ kLoLMonsterModifiers1, kRawDataBe16, false },
{ kLoLMonsterModifiers2, kRawDataBe16, false },
{ kLoLMonsterModifiers3, kRawDataBe16, false },
{ kLoLMonsterModifiers4, kRawDataBe16, false },
{ kLoLMonsterShiftOffsets, kRawData, false },
{ kLoLMonsterDirFlags, kRawData, false },
{ kLoLMonsterScaleY, kRawData, false },
{ kLoLMonsterScaleX, kRawData, false },
{ kLoLMonsterScaleWH, kRawDataBe16, false },
{ kLoLFlyingObjectShp, kLoLFlightShpData, false },
{ kLoLInventoryDesc, kRawDataBe16, false },
{ kLoLLevelShpList, kStringList, false },
{ kLoLLevelDatList, kStringList, false },
{ kLoLCompassDefs, kLoLCompassData, false },
{ kLoLItemPrices, kRawDataBe16, false },
{ kLoLStashSetup, kRawData, false },
{ kLoLDscWalls, kRawData, false },
{ kRpgCommonDscShapeIndex, kRawData, false },
{ kLoLDscOvlMap, kRawData, false },
{ kLoLDscScaleWidthData, kRawDataBe16, false },
{ kLoLDscScaleHeightData, kRawDataBe16, false },
{ kRpgCommonDscX, kRawDataBe16, false },
{ kLoLBaseDscY, kRawData, false },
{ kRpgCommonDscTileIndex, kRawData, false },
{ kRpgCommonDscUnk2, kRawData, false },
{ kRpgCommonDscDoorShapeIndex, kRawData, false },
{ kRpgCommonDscDimData1, kRawData, false },
{ kRpgCommonDscDimData2, kRawData, false },
{ kRpgCommonDscBlockMap, kRawData, false },
{ kRpgCommonDscDimMap, kRawData, false },
{ kLoLDscDoorScale, kRawDataBe16, false },
{ kLoLDscOvlIndex, kRawData, false },
{ kRpgCommonDscBlockIndex, kRawData, false },
{ kLoLDscDoor4, kRawDataBe16, false },
{ kRpgCommonDscDoorY2, kRawData, false },
{ kRpgCommonDscDoorFrameY1, kRawData, false },
{ kRpgCommonDscDoorFrameY2, kRawData, false },
{ kRpgCommonDscDoorFrameIndex1, kRawData, false },
{ kRpgCommonDscDoorFrameIndex2, kRawData, false },
{ kLoLDscDoorX, kRawDataBe16, false },
{ kLoLDscDoorY, kRawDataBe16, false },
{ kLoLScrollXTop, kRawData, false },
{ kLoLScrollYTop, kRawData, false },
{ kLoLScrollXBottom, kRawData, false },
{ kLoLScrollYBottom, kRawData, false },
{ kLoLButtonDefs, kLoLButtonData, false },
{ kLoLButtonList1, kRawData, false },
{ kLoLButtonList2, kRawData, false },
{ kLoLButtonList3, kRawData, false },
{ kLoLButtonList4, kRawData, false },
{ kLoLButtonList5, kRawData, false },
{ kLoLButtonList6, kRawData, false },
{ kLoLButtonList7, kRawData, false },
{ kLoLButtonList8, kRawData, false },
{ kLoLLegendData, kRawData, false },
{ kLoLMapCursorOvl, kRawData, false },
{ kLoLMapStringId, kRawDataBe16, false },
{ kLoLSpellbookAnim, kRawData, false },
{ kLoLSpellbookCoords, kRawData, false },
{ kLoLHealShapeFrames, kRawData, false },
{ kLoLLightningDefs, kRawData, false },
{ kLoLFireballCoords, kRawDataBe16, false },
{ kLoLCredits, kRawData, false },
{ kLoLHistory, kRawData, false },
{ -1, 0, 0 }
};
const ExtractFilename *getFilenameDesc(const int id) {
for (const ExtractFilename *i = extractFilenames; i->id != -1; ++i) {
if (i->id == id)
return i;
}
return 0;
}
bool isLangSpecific(const int id) {
const ExtractFilename *desc = getFilenameDesc(id);
if (!desc)
return false;
return desc->langSpecific;
}
// misc tables
const TypeTable gameTable[] = {
{ kKyra1, 0 },
{ kKyra2, 1 },
{ kKyra3, 2 },
{ kEoB1, 3 },
{ kEoB2, 4 },
{ kLoL, 5 },
{ -1, -1 }
};
byte getGameID(int game) {
return std::find(gameTable, ARRAYEND(gameTable) - 1, game)->value;
}
const TypeTable languageTable[] = {
{ UNK_LANG, 0 },
{ EN_ANY, 1 },
{ FR_FRA, 2 },
{ DE_DEU, 3 },
{ ES_ESP, 4 },
{ IT_ITA, 5 },
{ JA_JPN, 6 },
{ RU_RUS, 7 },
{ -1, -1 }
};
byte getLanguageID(int lang) {
return std::find(languageTable, ARRAYEND(languageTable) - 1, lang)->value;
}
const TypeTable platformTable[] = {
{ kPlatformDOS, 0 },
{ kPlatformAmiga, 1 },
{ kPlatformFMTowns, 2 },
{ kPlatformPC98, 3 },
{ kPlatformMacintosh, 4 },
{ -1, -1 }
};
byte getPlatformID(int platform) {
return std::find(platformTable, ARRAYEND(platformTable) - 1, platform)->value;
}
const TypeTable specialTable[] = {
{ kNoSpecial, 0 },
{ kTalkieVersion, 1 },
{ kDemoVersion, 2 },
{ kTalkieDemoVersion, 3 },
{ kOldFloppy, 4 },
{ -1, -1 }
};
byte getSpecialID(int special) {
return std::find(specialTable, ARRAYEND(specialTable) - 1, special)->value;
}
// filename processing
uint32 getFilename(int game, int plat, int spec, int lang, const ExtractFilename *fDesc) {
// GAME, PLATFORM, SPECIAL, ID, LANG
return ((getGameID(game) & 0xF) << 24) |
((getPlatformID(plat) & 0xF) << 20) |
((getSpecialID(spec) & 0xF) << 16) |
((fDesc->id & 0xFFF) << 4) |
((getLanguageID(fDesc->langSpecific ? lang : UNK_LANG) & 0xF) << 0);
}
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);
}
uint32 getFilename(const ResourceProvider *provider, const ExtractFilename *fDesc) {
return getFilename(provider->game, provider->platform, provider->special, provider->language, fDesc);
}
bool getFilename(char *dstFilename, const Game *g, const int id) {
sprintf(dstFilename, "%08X", getFilename(g, id));
return true;
}
// index generation
typedef uint16 GameDef;
GameDef createGameDef(const Game *g) {
return ((getGameID(g->game) & 0xF) << 12) |
((getPlatformID(g->platform) & 0xF) << 8) |
((getSpecialID(g->special) & 0xF) << 4) |
((getLanguageID(g->lang) & 0xF) << 0);
return 0;
}
// main processing
void printHelp(const char *f) {
printf("Usage:\n");
printf("%s output\n", f);
}
void outputAllResources(PAKFile &out);
void outputAllGames(PAKFile &out, std::vector<GameDef> &games);
int main(int argc, char *argv[]) {
if (argc != 2) {
printHelp(argv[0]);
return -1;
}
PAKFile out;
// First step: Write out all resources.
outputAllResources(out);
// Second step: Write all game version information
std::vector<GameDef> games;
outputAllGames(out, games);
// Third step: Write index file
byte *const indexBuffer = new byte[8 + 2 * games.size()];
byte *dst = indexBuffer;
WRITE_BE_UINT32(dst, kKyraDatVersion); dst += 4;
WRITE_BE_UINT32(dst, games.size()); dst += 4;
for (std::vector<GameDef>::const_iterator i = games.begin(), end = games.end(); i != end; ++i) {
WRITE_BE_UINT16(dst, *i); dst += 2;
}
if (!out.addFile("INDEX", indexBuffer, 8 + 2 * games.size())) {
error("couldn't write INDEX file");
}
if (!out.saveFile(argv[1])) {
error("couldn't save changes to '%s'", argv[1]);
}
uint8 digest[16];
if (!md5_file(argv[1], digest, 0))
error("couldn't calc. md5 for file '%s'", argv[1]);
FILE *f = fopen(argv[1], "ab");
if (!f)
error("couldn't open file '%s'", argv[1]);
if (fwrite(digest, 1, 16, f) != 16)
error("couldn't write md5sum to file '%s'", argv[1]);
fclose(f);
return 0;
}
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);
}
}
bool createIDMap(PAKFile &out, const Game *g, const int *needList);
void outputAllGames(PAKFile &out, std::vector<GameDef> &games) {
for (const Game *const *descs = gameDescs;
*descs; ++descs) {
for (const Game *game = *descs;
game->game != -1; ++game) {
const GameDef gameDef = createGameDef(game);
if (!createIDMap(out, game, getNeedList(game))) {
error("Could not create ID map for game %04X", gameDef);
}
games.push_back(gameDef);
}
}
}
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;
}