diff options
Diffstat (limited to 'engines/igor')
-rw-r--r-- | engines/igor/detection.cpp | 29 | ||||
-rw-r--r-- | engines/igor/igor.cpp | 200 | ||||
-rw-r--r-- | engines/igor/igor.h | 16 | ||||
-rw-r--r-- | engines/igor/parts/part_90.cpp | 5 | ||||
-rw-r--r-- | engines/igor/parts/part_main.cpp | 18 | ||||
-rw-r--r-- | engines/igor/staticres.cpp | 11 |
6 files changed, 146 insertions, 133 deletions
diff --git a/engines/igor/detection.cpp b/engines/igor/detection.cpp index 5e68f2df3b..130cf22780 100644 --- a/engines/igor/detection.cpp +++ b/engines/igor/detection.cpp @@ -40,7 +40,11 @@ static const IgorGameDescription igorGameDescriptions[] = { { "igor", "Demo 1.00s", - AD_ENTRY1s("IGOR.DAT", 0, 4086790), + { + { "IGOR.DAT", 0, 0, 4086790 }, + { "IGOR.FSD", 0, 0, 462564 }, + { 0, 0, 0, 0 } + }, Common::EN_ANY, Common::kPlatformPC, Common::ADGF_DEMO @@ -51,13 +55,32 @@ static const IgorGameDescription igorGameDescriptions[] = { { "igor", "Demo 1.10s", - AD_ENTRY1s("IGOR.DAT", 0, 4094103), + { + { "IGOR.DAT", 0, 0, 4094103 }, + { "IGOR.FSD", 0, 0, 462564 }, + { 0, 0, 0, 0 } + }, Common::EN_ANY, Common::kPlatformPC, Common::ADGF_DEMO }, Igor::kIdEngDemo110 }, + { + { + "igor", + "Talkie", + { + { "IGOR.EXE", 0, 0, 9115648 }, + { "IGOR.DAT", 0, 0, 61682719 }, + { 0, 0, 0, 0 } + }, + Common::ES_ESP, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + Igor::kIdSpaCD + }, { AD_TABLE_END_MARKER, 0 } }; @@ -69,7 +92,7 @@ static const PlainGameDescriptor igorGameDescriptors[] = { static const Common::ADParams igorDetectionParams = { (const byte *)igorGameDescriptions, sizeof(IgorGameDescription), - 0, // no md5 + 1024, // number of md5 bytes igorGameDescriptors, 0, "igor", diff --git a/engines/igor/igor.cpp b/engines/igor/igor.cpp index e0d98b1dbc..5e761a9e11 100644 --- a/engines/igor/igor.cpp +++ b/engines/igor/igor.cpp @@ -64,6 +64,8 @@ IgorEngine::IgorEngine(OSystem *system, int gameVersion) IgorEngine::~IgorEngine() { delete _midiPlayer; + free(_resourceEntries); + free(_soundOffsets); Common::clearAllSpecialDebugLevels(); free(_screenVGA); for (int i = 0; i < 4; ++i) { @@ -110,7 +112,7 @@ void IgorEngine::restart() { _actionCode = 0; _actionWalkPoint = 0; memset(_inputVars, 0, sizeof(_inputVars)); - memset(_musicSequenceTable, 0, sizeof(_musicSequenceTable)); + _musicData = 0; _talkDelay = _talkSpeechCounter = _talkDelayCounter = 0; memset(_dialogueTextsTable, 0, sizeof(_dialogueTextsTable)); @@ -140,7 +142,7 @@ void IgorEngine::restart() { _executeMainAction = 0; _executeRoomAction = 0; _previousMusic = 0; - memset(_musicSequenceTable, 0, sizeof(_musicSequenceTable)); + _musicData = 0; _actionCode = 0; _actionWalkPoint = 0; memset(_inputVars, 0, sizeof(_inputVars)); @@ -151,6 +153,11 @@ void IgorEngine::restart() { _updateDialogue = 0; _updateRoomBackground = 0; + _resourceEntriesCount = 0; + _resourceEntries = 0; + _soundOffsetsCount = 0; + _soundOffsets = 0; + _gameTicks = 0; } @@ -161,14 +168,17 @@ int IgorEngine::go() { if (_currentPart == 0) { _currentPart = kStartupPart; } - if (!_ovlFile.open("IGOR.DAT")) { - error("Unable to open 'IGOR.DAT'"); + const char *ovlFileName = "IGOR.DAT"; + const char *fsdFileName = "IGOR.FSD"; + if (_gameVersion == kIdSpaCD) { + ovlFileName = "IGOR.EXE"; + fsdFileName = "IGOR.DAT"; } - if (!_sndFile.open("IGOR.FSD")) { - error("Unable to open 'IGOR.FSD'"); + if (!_ovlFile.open(ovlFileName)) { + error("Unable to open '%s'", ovlFileName); } - if (!_tblFile.open("IGOR.TBL")) { - error("Unable to open 'IGOR.TBL'"); + if (!_sndFile.open(fsdFileName)) { + error("Unable to open '%s'", fsdFileName); } readResourceTableFile(); loadMainTexts(); @@ -180,25 +190,43 @@ int IgorEngine::go() { PART_MAIN(); _ovlFile.close(); _sndFile.close(); - _tblFile.close(); return 0; } void IgorEngine::readResourceTableFile() { - if (_tblFile.readUint32BE() == MKID_BE('ITBL') && _tblFile.readUint32BE() == 1) { + Common::File tblFile; + uint32 resourcesEntriesOffset = 0, soundEntriesOffset = 0; + if (tblFile.open("IGOR.TBL") && tblFile.readUint32BE() == MKID_BE('ITBL') && tblFile.readUint32BE() == 2) { + tblFile.skip(4); uint32 borlandOverlaySize = _ovlFile.size(); - int gameVersionsCount = _tblFile.readByte(); + int gameVersionsCount = tblFile.readByte(); for (int i = 0; i < gameVersionsCount; ++i) { - uint32 size = _tblFile.readUint32BE(); - uint32 offs = _tblFile.readUint32BE(); + uint32 size = tblFile.readUint32BE(); if (size == borlandOverlaySize) { - _tblFile.seek(offs); - _resourceEntriesCount = _tblFile.readUint16BE(); - _resourceEntriesOffset = offs + 2; - return; + resourcesEntriesOffset = tblFile.readUint32BE(); + soundEntriesOffset = tblFile.readUint32BE(); + break; } + tblFile.skip(8); } } + if (resourcesEntriesOffset != 0 && soundEntriesOffset != 0) { + tblFile.seek(resourcesEntriesOffset); + _resourceEntriesCount = tblFile.readUint16BE(); + _resourceEntries = (ResourceEntry *)malloc(sizeof(ResourceEntry) * _resourceEntriesCount); + for (int i = 0; i < _resourceEntriesCount; ++i) { + _resourceEntries[i].id = tblFile.readUint16BE(); + _resourceEntries[i].offs = tblFile.readUint32BE(); + _resourceEntries[i].size = tblFile.readUint32BE(); + } + tblFile.seek(soundEntriesOffset); + _soundOffsetsCount = tblFile.readUint16BE(); + _soundOffsets = (uint32 *)malloc(sizeof(uint32) * _soundOffsetsCount); + for (int i = 0; i < _soundOffsetsCount; ++i) { + _soundOffsets[i] = tblFile.readUint32BE(); + } + return; + } error("Unable to read 'IGOR.TBL'"); } @@ -255,11 +283,12 @@ void IgorEngine::waitForTimer(int ticks) { return; } _gameTicks += kTimerTicksCount; - if (_gameTicks == 64) { + if (_gameTicks == 64) { // TODO: original switches cursors more often _gameTicks = 0; setCursor(_currentCursor); _currentCursor = (_currentCursor + 1) & 3; } + // TODO: updateMusic(); } void IgorEngine::copyArea(uint8 *dst, int dstOffset, int dstPitch, const uint8 *src, int srcPitch, int w, int h, bool transparent) { @@ -280,89 +309,60 @@ void IgorEngine::copyArea(uint8 *dst, int dstOffset, int dstPitch, const uint8 * } int IgorEngine::getRandomNumber(int m) { - assert(m != 0); - return rand() % m; + assert(m > 0); + return _rnd.getRandomNumber(m - 1); +} + +void IgorEngine::startMusic(int cmf) { + _midiPlayer->stopMusic(); + free(_musicData); + int musicDataSize; + _musicData = loadData(cmf, 0, &musicDataSize); + _midiPlayer->playMusic(_musicData, musicDataSize); } void IgorEngine::playMusic(int num) { debugC(9, kDebugEngine, "playMusic() %d", num); - const int *seq = 0; - switch (num) { - case 2: { - static const int cmf[] = { CMF_2_1, CMF_2_2, CMF_2_3, CMF_2_4, 0 }; - seq = cmf; - } - break; - case 3: { - static const int cmf[] = { CMF_3, 0 }; - seq = cmf; - } - break; - case 4: { - static const int cmf[] = { CMF_4, 0 }; - seq = cmf; - } - break; - case 7: { - static const int cmf[] = { CMF_7_1, CMF_7_2, CMF_7_3, CMF_7_4, 0 }; - seq = cmf; - } - break; - case 8: { - static const int cmf[] = { CMF_8, 0 }; - seq = cmf; - } - break; - case 9: { - static const int cmf[] = { CMF_9, 0 }; - seq = cmf; - } - break; - case 10: { - static const int cmf[] = { CMF_10, 0 }; - seq = cmf; - } - break; - case 11: { - static const int cmf[] = { CMF_11, 0 }; - seq = cmf; - } - break; - case 12: { - static const int cmf[] = { CMF_12, 0 }; - seq = cmf; - } - break; - } - if (seq) { - for (int i = 0; i < 5; ++i) { - free(_musicSequenceTable[i].data); - } - for (int i = 0; seq[i]; ++i) { - _musicSequenceTable[i].data = loadData(seq[i], 0, &_musicSequenceTable[i].dataSize); - } - } + static const int cmf[] = { 0, 0, CMF_2_1, CMF_3, CMF_4, 0, 0, CMF_7_1, CMF_8, CMF_9, CMF_10, CMF_11, CMF_12 }; + assert(num < ARRAYSIZE(cmf) && cmf[num] != 0); _gameState.musicNum = num; _gameState.musicSequenceIndex = 1; - _midiPlayer->playMusic(_musicSequenceTable[0].data, _musicSequenceTable[0].dataSize); + if (_gameVersion == kIdSpaCD) { + // different file format + return; + } + startMusic(cmf[num]); } void IgorEngine::updateMusic() { + static const int cmf2Seq[] = { CMF_2_1, CMF_2_2, CMF_2_3, CMF_2_4 }; + static const int cmf7Seq[] = { CMF_7_1, CMF_7_2, CMF_7_3, CMF_7_4 }; if (_gameState.jumpToNextMusic) { - if (_gameState.musicNum == 2) { + switch (_gameState.musicNum) { + case 2: _gameState.musicSequenceIndex = getRandomNumber(4) + 1; + startMusic(cmf2Seq[_gameState.musicSequenceIndex - 1]); // _timerHandler0x1CCounter = 5; - } else if (_gameState.musicNum == 3 || _gameState.musicNum == 4 || _gameState.musicNum == 8 || _gameState.musicNum == 9 || _gameState.musicNum == 10) { -// _timerHandler0x1CCounter = 50; - } else if (_gameState.musicNum == 7) { + break; + case 7: if (_gameState.musicSequenceIndex == 4) { _gameState.musicSequenceIndex = 1; } else { ++_gameState.musicSequenceIndex; } + startMusic(cmf7Seq[_gameState.musicSequenceIndex - 1]); // _timerHandler0x1CCounter = 5; - } else if (_gameState.musicNum == 11) { + break; + case 3: + case 4: + case 8: + case 9: + case 10: +// _timerHandler0x1CCounter = 50; + break; + case 11: // _timerHandler0x1CCounter = 5; + break; } } } @@ -377,7 +377,8 @@ void IgorEngine::playSound(int num, int fl) { return; } --num; - _sndFile.seek(_fdsOffsetsTable[num]); + assert(num >= 0 && num < _soundOffsetsCount); + _sndFile.seek(_soundOffsets[num]); Audio::AudioStream *stream = Audio::makeVOCStream(_sndFile); if (stream) { _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, stream); @@ -633,30 +634,31 @@ int IgorEngine::getObjectFromInventory(int x) const { return 0; } -ResourceEntry IgorEngine::findData(int id) { - assert(id >= 1 && id <= _resourceEntriesCount); - _tblFile.seek(_resourceEntriesOffset + (id - 1) * 10); - ResourceEntry re; - re.id = _tblFile.readUint16BE(); - re.offs = _tblFile.readUint32BE(); - re.size = _tblFile.readUint32BE(); - assert(re.id == id); +static int compareResourceEntry(const void *a, const void *b) { + int id = *(const int *)a; + const ResourceEntry *entry = (const ResourceEntry *)b; + return id - entry->id; +} + +ResourceEntry *IgorEngine::findData(int id) { + ResourceEntry *re = (ResourceEntry *)bsearch(&id, _resourceEntries, _resourceEntriesCount, sizeof(ResourceEntry), compareResourceEntry); + assert(re); return re; } uint8 *IgorEngine::loadData(int id, uint8 *dst, int *size) { - ResourceEntry re = findData(id); - debugC(9, kDebugResource, "loadData() id %d offset %d size %d", id, re.offs, re.size); + debugC(9, kDebugResource, "loadData() id %d", id); + ResourceEntry *re = findData(id); if (!dst) { - dst = (uint8 *)malloc(re.size); + dst = (uint8 *)malloc(re->size); if (!dst) { - error("Unable to allocate %d bytes", re.size); + error("Unable to allocate %d bytes", re->size); } } - _ovlFile.seek(re.offs); - _ovlFile.read(dst, re.size); + _ovlFile.seek(re->offs); + _ovlFile.read(dst, re->size); if (size) { - *size = re.size; + *size = re->size; } return dst; } @@ -811,7 +813,7 @@ void IgorEngine::loadAnimData(const int *anm, int loadOffset) { void IgorEngine::loadActionData(int act) { if (act != 0) { - assert(findData(act).size <= 0x2000); + assert(findData(act)->size <= 0x2000); loadData(act, _roomActionsTable); } } diff --git a/engines/igor/igor.h b/engines/igor/igor.h index a71c741c89..6659d21132 100644 --- a/engines/igor/igor.h +++ b/engines/igor/igor.h @@ -311,6 +311,7 @@ protected: int getRandomNumber(int m); void handleOptionsMenu(); void handlePause(); + void startMusic(int cmf); void playMusic(int num); void updateMusic(); void playSound(int num, int fl); @@ -323,7 +324,7 @@ protected: void startIgorDialogue(); void waitForEndOfIgorDialogue(); int getObjectFromInventory(int x) const; - ResourceEntry findData(int num); + ResourceEntry *findData(int num); uint8 *loadData(int num, uint8 *dst = 0, int *size = 0); void decodeMainText(const uint8 *p); void decodeRoomStrings(const uint8 *p, bool skipObjectNames = false); @@ -400,9 +401,10 @@ protected: MidiPlayer *_midiPlayer; + Common::RandomSource _rnd; + Common::File _ovlFile; Common::File _sndFile; - Common::File _tblFile; Audio::SoundHandle _sfxHandle; @@ -468,10 +470,7 @@ protected: ExecuteActionProc _executeMainAction; ExecuteActionProc _executeRoomAction; uint8 _previousMusic; - struct { - uint8 *data; - int dataSize; - } _musicSequenceTable[5]; + uint8 *_musicData; Action _currentAction; uint8 _actionCode; uint8 _actionWalkPoint; @@ -487,7 +486,9 @@ protected: UpdateRoomBackgroundProc _updateRoomBackground; int _gameTicks; int _resourceEntriesCount; - int _resourceEntriesOffset; + ResourceEntry *_resourceEntries; + int _soundOffsetsCount; + uint32 *_soundOffsets; char _saveStateDescriptions[kMaxSaveStates][100]; static const uint8 _dialogueColor[]; @@ -504,7 +505,6 @@ protected: static const uint8 _walkScaleTable[]; static const uint8 _mouseCursorMask[]; static const uint8 _mouseCursorData[]; - static const uint32 _fdsOffsetsTable[]; // diff --git a/engines/igor/parts/part_90.cpp b/engines/igor/parts/part_90.cpp index c069d5d34e..c503d155f2 100644 --- a/engines/igor/parts/part_90.cpp +++ b/engines/igor/parts/part_90.cpp @@ -69,10 +69,9 @@ void IgorEngine::PART_90() { _inputVars[kInputEscape] = 0; fadeOutPalette(768); if (_currentPart != kInvalidPart) { - if (_currentPart == 904) { + ++_currentPart; + if ((_gameVersion == kIdSpaCD && _currentPart == 904) || _currentPart == 905) { _currentPart = 850; - } else { - ++_currentPart; } } } diff --git a/engines/igor/parts/part_main.cpp b/engines/igor/parts/part_main.cpp index 44731b72b8..f3c99b8de1 100644 --- a/engines/igor/parts/part_main.cpp +++ b/engines/igor/parts/part_main.cpp @@ -585,13 +585,13 @@ void IgorEngine::UPDATE_OBJECT_STATE(int num) { if (num == 1 || num == 255) { switch (_objectsState[0]) { case 0: - memcpy(_globalObjectNames + 0x592 / 62, " bottle of whisky", 30); + strcpy(_globalObjectNames[23], " bottle of whisky"); break; case 1: - memcpy(_globalObjectNames + 0x592 / 62, " empty bottle", 30); + strcpy(_globalObjectNames[23], " empty bottle"); break; case 2: - memcpy(_globalObjectNames + 0x592 / 62, " bottle of water", 30); + strcpy(_globalObjectNames[23], " bottle of water"); break; } } @@ -599,21 +599,21 @@ void IgorEngine::UPDATE_OBJECT_STATE(int num) { switch (_objectsState[1]) { case 0: _inventoryImages[23] = 27; - memcpy(_globalObjectNames + 0x5D0 / 62, " lizard", 30); + strcpy(_globalObjectNames[24], " lizard"); break; default: _inventoryImages[23] = 35; - memcpy(_globalObjectNames + 0x5D0 / 62, " fat lizard", 30); + strcpy(_globalObjectNames[24], " fat lizard"); break; } } if (num == 4 || num == 255) { switch (_objectsState[3]) { case 0: - memcpy(_globalObjectNames + 0x554 / 62, " Caroline%s folder", 30); + strcpy(_globalObjectNames[22], " Caroline%s folder"); break; case 1: - memcpy(_globalObjectNames + 0x554 / 62, " Philip%s folder", 30); + strcpy(_globalObjectNames[22], " Philip%s folder"); break; } } @@ -632,10 +632,10 @@ void IgorEngine::UPDATE_OBJECT_STATE(int num) { } if (num == 8 || num == 255) { if (_objectsState[7] == 0) { - memcpy(_globalObjectNames + 0x60E / 62, " statuette", 30); + strcpy(_globalObjectNames[25], " statuette"); _inventoryImages[24] = 29; } else { - memcpy(_globalObjectNames + 0x60E / 62, " reward", 30); + strcpy(_globalObjectNames[25], " reward"); _inventoryImages[24] = 39; } } diff --git a/engines/igor/staticres.cpp b/engines/igor/staticres.cpp index 31761ebccf..b44090ce34 100644 --- a/engines/igor/staticres.cpp +++ b/engines/igor/staticres.cpp @@ -904,17 +904,6 @@ const uint8 IgorEngine::_mouseCursorData[] = { 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05 }; -const uint32 IgorEngine::_fdsOffsetsTable[] = { - 0x000000, 0x000001, 0x000002, 0x0018E4, 0x003301, 0x003302, 0x003303, 0x003304, - 0x003305, 0x003306, 0x003307, 0x003308, 0x003309, 0x003EEB, 0x005908, 0x005909, - 0x00590A, 0x01542C, 0x016418, 0x016419, 0x01D37F, 0x01E4A1, 0x01F42C, 0x01F95F, - 0x026B80, 0x026B81, 0x026B82, 0x026B83, 0x026B84, 0x026B85, 0x026B86, 0x026B87, - 0x026B88, 0x02CA59, 0x02DD76, 0x02ED6A, 0x02ED6B, 0x02ED6C, 0x02ED6D, 0x02ED6E, - 0x02ED6F, 0x02ED70, 0x02ED71, 0x02ED72, 0x02ED73, 0x047F4F, 0x047F50, 0x04AC64, - 0x04EFC5, 0x052755, 0x052756, 0x052988, 0x058119, 0x05811A, 0x06202A, 0x06202B, - 0x06202C, 0x06202D, 0x06202E, 0x06202F, 0x062030, 0x062031, 0x070CB2 -}; - const uint8 IgorEngine::PAL_48_1[] = { 0x2D, 0x16, 0x00, 0x3D, 0x26, 0x01, 0x32, 0x32, 0x24, 0x16, 0x1D, 0x16, 0x12, 0x19, 0x12, 0x0B, 0x12, 0x0B, 0x32, 0x32, 0x24, 0x16, 0x1D, 0x16, 0x12, 0x19, 0x12, 0x0B, 0x12, 0x0B, 0x3D, 0x3D, |