From 42e03bd70720643c0866abd7d6da50529d2c1f03 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Thu, 11 May 2006 19:43:30 +0000 Subject: - Sound! Still a bit glitchy, though: - Negative frequences?!? Maybe "SFX"? - No sound for a small part of the intro (there aren't any sndKeys covering that part either) - A rythm-instrument (hi-hat?) in the titlemusic isn't played as one - More differences in the drawing functions fleshed out - Some of the goblin handling functions written - More unnamed functions and variables, wheeee... svn-id: r22410 --- engines/gob/game.cpp | 120 +++++++++++- engines/gob/game.h | 6 +- engines/gob/game_v2.cpp | 5 +- engines/gob/gob.cpp | 8 +- engines/gob/goblin.cpp | 289 +++++++++++++++++---------- engines/gob/goblin.h | 46 ++++- engines/gob/goblin_v1.cpp | 140 +++++++++++++ engines/gob/goblin_v2.cpp | 105 ++++++++++ engines/gob/init.cpp | 4 +- engines/gob/inter.cpp | 43 ++-- engines/gob/inter.h | 24 ++- engines/gob/inter_v1.cpp | 35 +++- engines/gob/inter_v2.cpp | 487 +++++++++++++++++++++++++++++++--------------- engines/gob/map.cpp | 308 ----------------------------- engines/gob/map.h | 20 +- engines/gob/map_v1.cpp | 346 ++++++++++++++++++++++++++++++++ engines/gob/map_v2.cpp | 192 ++++++++++++++++++ engines/gob/module.mk | 4 + engines/gob/mult.cpp | 8 +- engines/gob/mult.h | 38 +++- engines/gob/mult_v1.cpp | 6 +- engines/gob/mult_v2.cpp | 96 +++++++-- engines/gob/music.cpp | 34 +++- engines/gob/music.h | 13 +- engines/gob/sound.cpp | 11 +- engines/gob/sound.h | 2 +- engines/gob/util.h | 18 ++ engines/gob/video.cpp | 131 +------------ engines/gob/video.h | 8 +- engines/gob/video_v1.cpp | 129 ++++++++++++ engines/gob/video_v2.cpp | 149 ++++++++++++++ 31 files changed, 2027 insertions(+), 798 deletions(-) create mode 100644 engines/gob/goblin_v1.cpp create mode 100644 engines/gob/goblin_v2.cpp create mode 100644 engines/gob/map_v1.cpp create mode 100644 engines/gob/map_v2.cpp (limited to 'engines') diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index a737502060..adfaec9c4c 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -64,8 +64,11 @@ Game::Game(GobEngine *vm) : _vm(vm) { _collStackElemSizes[i] = 0; } - for (i = 0; i < 20; i++) + for (i = 0; i < 60; i++) { _soundSamples[i] = 0; + _soundIds[i] = 0; + _soundTypes[i] = 0; + } _curTotFile[0] = 0; _curExtFile[0] = 0; @@ -1372,8 +1375,6 @@ void Game::start(void) { void Game::totSub(int8 flags, char *newTotFile) { int8 curBackupPos; - warning("totSub(%d, \"%s\");", flags, newTotFile); - if (_backupedCount >= 5) return; @@ -1437,6 +1438,74 @@ void Game::totSub(int8 flags, char *newTotFile) { strcat(_curExtFile, ".EXT"); } +void Game::switchTotSub(int16 index, int16 skipPlay) { + int16 backupedCount; + int16 curBackupPos; + + if ((_backupedCount - index) < 1) + return; + + curBackupPos = _curBackupPos; + backupedCount = _backupedCount; + if (_curBackupPos == _backupedCount) { + _cursorXDeltaArray[_backupedCount] = _vm->_draw->_cursorXDeltaVar; + _cursorYDeltaArray[_backupedCount] = _vm->_draw->_cursorYDeltaVar; + _totTextDataArray[_backupedCount] = _totTextData; + _totFileDataArray[_backupedCount] = _totFileData; + _totResourceTableArray[_backupedCount] = _totResourceTable; + _extTableArray[_backupedCount] = _extTable; + _extHandleArray[_backupedCount] = _extHandle; + _imFileDataArray[_backupedCount] = _imFileData; + _variablesArray[_backupedCount] = _vm->_global->_inter_variables; + strcpy(_curTotFileArray[_backupedCount], _curTotFile); + _backupedCount++; + } + _curBackupPos -= index; + if (index >= 0) + _curBackupPos--; + + _vm->_draw->_cursorXDeltaVar = _cursorXDeltaArray[_curBackupPos]; + _vm->_draw->_cursorYDeltaVar = _cursorYDeltaArray[_curBackupPos]; + _totTextData = _totTextDataArray[_curBackupPos]; + _totFileData = _totFileDataArray[_curBackupPos]; + _totResourceTable = _totResourceTableArray[_curBackupPos]; + _extTable = _extTableArray[_curBackupPos]; + _extHandle = _extHandleArray[_curBackupPos]; + _imFileData = _imFileDataArray[_curBackupPos]; + _vm->_global->_inter_variables = _variablesArray[_curBackupPos]; + strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); + strcpy(_curExtFile, _curTotFile); + _curExtFile[strlen(_curExtFile)-4] = '\0'; + strcat(_curExtFile, ".EXT"); + + if (_vm->_inter->_terminate != 0) + return; + + _vm->_game->pushCollisions(0); + _vm->_game->playTot(skipPlay); + + if (_vm->_inter->_terminate != 2) + _vm->_inter->_terminate = 0; + + _vm->_game->popCollisions(); + + _curBackupPos = curBackupPos; + _backupedCount = backupedCount; + _vm->_draw->_cursorXDeltaVar = _cursorXDeltaArray[_curBackupPos]; + _vm->_draw->_cursorYDeltaVar = _cursorYDeltaArray[_curBackupPos]; + _totTextData = _totTextDataArray[_curBackupPos]; + _totFileData = _totFileDataArray[_curBackupPos]; + _totResourceTable = _totResourceTableArray[_curBackupPos]; + _extTable = _extTableArray[_curBackupPos]; + _extHandle = _extHandleArray[_curBackupPos]; + _imFileData = _imFileDataArray[_curBackupPos]; + _vm->_global->_inter_variables = _variablesArray[_curBackupPos]; + strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); + strcpy(_curExtFile, _curTotFile); + _curExtFile[strlen(_curExtFile)-4] = '\0'; + strcat(_curExtFile, ".EXT"); +} + int16 Game::openLocTextFile(char *locTextFile, int language) { int n; @@ -1634,4 +1703,49 @@ void Game::sub_BB28(void) { _vm->_draw->freeSprite(21); } +Snd::SoundDesc *Game::loadSND(const char *path, int8 arg_4) { + Snd::SoundDesc *soundDesc; + int32 dsize; + char *data; + char *dataPtr; + + soundDesc = new Snd::SoundDesc; + + data = _vm->_dataio->getData(path); + if (data == 0) { + delete soundDesc; + return 0; + } + soundDesc->data = data; + soundDesc->flag = *data & 0x7F; + if (*data == 0) + soundDesc->flag = 8; + dataPtr = data + 4; + + WRITE_LE_UINT16(dataPtr, READ_BE_UINT16(dataPtr)); + + WRITE_LE_UINT32(data, (READ_LE_UINT32(data) >> 24) + ((READ_LE_UINT16(data) & 0xFF00) << 8) + ((READ_LE_UINT16(data + 2) & 0xFF) >> 8)); + + soundDesc->size = READ_LE_UINT32(data); + dsize = _vm->_dataio->getDataSize(path) - 6; + if (dsize > soundDesc->size) + soundDesc->size = dsize; + + soundDesc->frequency = READ_LE_UINT16(dataPtr); + soundDesc->data += 6; + soundDesc->timerTicks = 1193180 / READ_LE_UINT16(dataPtr); + + if (arg_4 & 2) + arg_4 |= 1; + if ((soundDesc->frequency < 4700) && (arg_4 & 1)) + arg_4 &= 0xFE; + + if (arg_4 & 1) { + if ((_vm->_global->_soundFlags & BLASTER_FLAG) || (_vm->_global->_soundFlags & PROAUDIO_FLAG)) { + } + } + + return soundDesc; +} + } // End of namespace Gob diff --git a/engines/gob/game.h b/engines/gob/game.h index d0c70e5fba..7e14a54091 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -110,7 +110,9 @@ public: int16 _extHandle; - Snd::SoundDesc *_soundSamples[20]; + Snd::SoundDesc *_soundSamples[60]; + int16 _soundIds[60]; + int8 _soundTypes[60]; char _totToLoad[20]; @@ -157,7 +159,9 @@ public: void loadImFile(void); void start(void); void totSub(int8 flags, char *newTotFile); + void switchTotSub(int16 index, int16 skipPlay); char *loadLocTexts(void); + Snd::SoundDesc *loadSND(const char *path, int8 arg_4); virtual void playTot(int16 skipPlay) = 0; virtual void clearCollisions(void) = 0; diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index 8da4a92e03..337b629b33 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -238,8 +238,9 @@ void Game_v2::playTot(int16 skipPlay) { } _vm->_snd->stopSound(0); - for (i = 0; i < 20; i++) - freeSoundSlot(i); + for (i = 0; i < 60; i++) + if ((_soundTypes[i] & 8) == 0) + freeSoundSlot(i); if (_totToLoad[0] == 0) break; diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 7fa54445f6..b883de37c0 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -196,8 +196,6 @@ int GobEngine::init() { _anim = new Anim(); _cdrom = new CDROM(this); _dataio = new DataIO(this); - _goblin = new Goblin(this); - _map = new Map(this); _pack = new Pack(); _palanim = new PalAnim(this); _scenery = new Scenery(this); @@ -211,6 +209,8 @@ int GobEngine::init() { _game = new Game_v1(this); _video = new Video_v1(this); _init = new Init_v1(this); + _map = new Map_v1(this); + _goblin = new Goblin_v1(this); } else if (_features & Gob::GF_GOB2) { _inter = new Inter_v2(this); @@ -220,10 +220,12 @@ int GobEngine::init() { _game = new Game_v2(this); _video = new Video_v2(this); _init = new Init_v2(this); + _map = new Map_v2(this); + _goblin = new Goblin_v2(this); } else error("GobEngine::init(): Unknown version of game engine"); - if ((_features & Gob::GF_MAC) || (_features & Gob::GF_GOB1)) + if ((_features & Gob::GF_MAC) || (_features & Gob::GF_GOB1) || (_features & Gob::GF_GOB2)) _music = new Music(this); _system->beginGFXTransaction(); diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp index 629a31bd05..05bfe6fc5a 100644 --- a/engines/gob/goblin.cpp +++ b/engines/gob/goblin.cpp @@ -34,10 +34,13 @@ #include "gob/dataio.h" #include "gob/cdrom.h" #include "gob/music.h" +#include "gob/mult.h" namespace Gob { Goblin::Goblin(GobEngine *vm) : _vm(vm) { + int i; + _goesAtTarget = 0; _readyToAct = 0; _gobAction = 0; @@ -68,7 +71,7 @@ Goblin::Goblin(GobEngine *vm) : _vm(vm) { _noPick = 0; _objList = 0; - int i; + for (i = 0; i < 4; i++) _goblins[i] = 0; _currentGoblin = 0; @@ -144,6 +147,19 @@ Goblin::Goblin(GobEngine *vm) : _vm(vm) { } _objCount = 0; _gobsCount = 0; + + _soundSlotsCount = 0; + for (i = 0; i < 60; i++) + _soundSlots[i] = -1; + + warning("GOB2 Stub! _word_2F9C0, _word_2F9BE, _word_2F9BC, _word_2F9BA, _dword_2F9B6, _dword_2F9B2"); + _word_2F9C0 = 0; + _word_2F9BE = 0; + _word_2F9BC = 0; + _word_2F9BA = 0; + _dword_2F9B6 = 0; + _dword_2F9B2 = 0; + _dword_2F2A4 = 0; } char Goblin::rotateState(int16 from, int16 to) { @@ -494,52 +510,6 @@ void Goblin::animateObjects(void) { } } -void Goblin::placeObject(Gob_Object *objDesc, char animated) { - int16 layer; - - if (objDesc->stateMach[objDesc->state][0] != 0) { - objDesc->animation = - objDesc->stateMach[objDesc->state][0]->animation; - - objDesc->noTick = 0; - objDesc->toRedraw = 1; - objDesc->doAnim = animated; - - objDesc->maxTick = 1; - objDesc->tick = 1; - objDesc->curFrame = 0; - objDesc->type = 0; - objDesc->actionStartState = 0; - objDesc->nextState = -1; - objDesc->multState = -1; - objDesc->stateColumn = 0; - objDesc->curLookDir = 0; - objDesc->visible = 1; - objDesc->pickable = 0; - objDesc->unk14 = 0; - - objDesc->relaxTime = _vm->_util->getRandom(30); - - layer = objDesc->stateMach[objDesc->state][0]->layer; - _vm->_scenery->updateAnim(layer, 0, objDesc->animation, 0, - objDesc->xPos, objDesc->yPos, 0); - - objDesc->order = _vm->_scenery->_toRedrawBottom / 24 + 3; - - objDesc->left = objDesc->xPos; - objDesc->right = objDesc->xPos; - objDesc->dirtyLeft = objDesc->xPos; - objDesc->dirtyRight = objDesc->xPos; - - objDesc->top = objDesc->yPos; - objDesc->bottom = objDesc->yPos; - objDesc->dirtyTop = objDesc->yPos; - objDesc->dirtyBottom = objDesc->yPos; - - _vm->_util->listInsertBack(_objList, objDesc); - } -} - int16 Goblin::getObjMaxFrame(Gob_Object * objDesc) { int16 layer; @@ -1816,63 +1786,6 @@ int16 Goblin::doMove(Gob_Object *gobDesc, int16 cont, int16 action) { return gobIndex; } -void Goblin::freeObjects(void) { - int16 i; - int16 state; - int16 col; - - for (i = 0; i < 16; i++) { - if (_soundData[i] == 0) - continue; - - _vm->_snd->freeSoundDesc(_soundData[i]); - _soundData[i] = 0; - } - - for (i = 0; i < 4; i++) { - if (_goblins[i] == 0) - continue; - - _goblins[i]->stateMach = _goblins[i]->realStateMach; - - for (state = 0; state < 40; state++) { - for (col = 0; col < 6; col++) { - delete _goblins[i]->stateMach[state][col]; - _goblins[i]->stateMach[state][col] = 0; - } - } - - if (i == 3) { - for (state = 40; state < 70; state++) { - delete _goblins[3]->stateMach[state][0]; - _goblins[3]->stateMach[state][0] = 0; - } - } - - delete[] _goblins[i]->stateMach; - delete _goblins[i]; - _goblins[i] = 0; - } - - for (i = 0; i < 20; i++) { - if (_objects[i] == 0) - continue; - - _objects[i]->stateMach = _objects[i]->realStateMach; - - for (state = 0; state < 40; state++) { - for (col = 0; col < 6; col++) { - delete _objects[i]->stateMach[state][col]; - _objects[i]->stateMach[state][col] = 0; - } - } - - delete[] _objects[i]->stateMach; - delete _objects[i]; - _objects[i] = 0; - } -} - void Goblin::zeroObjects(void) { int16 i; @@ -1906,10 +1819,10 @@ void Goblin::loadObjects(char *source) { _vm->_map->loadMapObjects(source); for (i = 0; i < _gobsCount; i++) - placeObject(_goblins[i], 0); + placeObject(_goblins[i], 0, 0, 0, 0, 0); for (i = 0; i < _objCount; i++) { - placeObject(_objects[i], 1); + placeObject(_objects[i], 1, 0, 0, 0, 0); } initVarPointers(); @@ -2378,4 +2291,168 @@ int16 Goblin::treatItem(int16 action) { } } +void Goblin::sub_19BD3(void) { + Mult::Mult_Object *obj0; + Mult::Mult_Object *obj1; + Mult::Mult_AnimData *anim0; + Mult::Mult_AnimData *anim1; + int16 varVal; + int16 var_2; + int16 var_4; + int16 var_6; + int16 var_8; + int16 var_A; + int16 var_C; + int16 di; + int16 si; + + obj0 = &(_vm->_mult->_objects[0]); + obj1 = &(_vm->_mult->_objects[1]); + anim0 = obj0->pAnimData; + anim1 = obj1->pAnimData; + + si = anim0->state; + di = anim1->state; + + if (anim0->someFlag == 0) { + if ((_word_2F9BC == 0) && (anim0->isStatic == 0)) { + if ((VAR(_dword_2F9B6) == 0) && (si == 28)) { + si = _vm->_util->getRandom(3) + 24; + warning("GOB2 Stub! sub_195C7(0, si);"); + WRITE_VAR(_dword_2F9B6, 100); + } else + WRITE_VAR(_dword_2F9B6, VAR(_dword_2F9B6) - 1); + } + if ((si == 8) || (si == 9) || (si == 29)) + anim0->field_10 = 6; + } + if (anim1->someFlag == 0) { + if((_word_2F9BA == 0) && (anim1->isStatic == 0)) { + if ((VAR(_dword_2F9B2) == 0) && (di == 28)) { + di = _vm->_util->getRandom(3) + 24; + warning("GOB2 Stub! sub_195C7(1, di);"); + WRITE_VAR(_dword_2F9B2, 100); + } else + WRITE_VAR(_dword_2F9B2, VAR(_dword_2F9B2) - 1); + } + if ((di == 8) || (di == 9) || (di == 29)) + anim1->field_10 = 6; + } + + if ((anim0->someFlag == 1) && (anim0->isStatic == 0) && + ((anim0->state == 28) || (anim0->state == 29))) + anim0->field_10 = 0; + if ((anim1->someFlag == 1) && (anim1->isStatic == 0) && + ((anim1->state == 28) || (anim1->state == 29))) + anim1->field_10 = 0; + + if (VAR(18) != ((uint32) -1)) { + if (anim0->layer == 44) + anim0->field_10 = 4; + else if(anim0->layer == 45) + anim0->field_10 = 0; + if (anim0->someFlag == 0) + anim0->field_10 = 6; + } + if (VAR(19) != ((uint32) -1)) { + if (anim1->layer == 48) + anim1->field_10 = 4; + else if(anim1->layer == 49) + anim1->field_10 = 0; + if (anim1->someFlag == 0) + anim1->field_10 = 6; + } + + if ((anim0->layer == 45) && (anim0->field_10 == 4) && (anim0->field_12 == 5) && + (VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) { + warning("GOB2 Stub! sub_195C7(0, 19);"); + } + if ((anim0->layer == 44) && (anim0->field_10 == 0) && (anim0->field_12 == 5) && + (VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) { + warning("GOB2 Stub! sub_195C7(0, 16);"); + } + if ((anim1->layer == 49) && (anim1->field_10 == 4) && (anim1->field_12 == 5) && + (VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) { + warning("GOB2 Stub! sub_195C7(1, 19);"); + } + if ((anim1->layer == 48) && (anim1->field_10 == 0) && (anim1->field_12 == 5) && + (VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) { + warning("GOB2 Stub! sub_195C7(1, 16);"); + } + + var_2 = obj0->goblinX; + var_4 = obj1->goblinX; + var_6 = obj0->goblinY; + var_8 = obj1->goblinY; + di = anim0->field_13; + si = anim0->field_14; + var_A = anim1->field_13; + var_C = anim1->field_14; + + varVal = _vm->_util->readVariableByte(_dword_2F2A4 + var_6 * 40 + var_2); + if ((varVal > 17) && (varVal < 21)) + warning("GOB2 Stub! sub_195C7(anim0);"); + varVal = _vm->_util->readVariableByte(_dword_2F2A4 + var_8 * 40 + var_4); + if ((varVal > 17) && (varVal < 21)) + warning("GOB2 Stub! sub_19B45(anim1);"); + + if ((di < 0) || (di > 39) || (si < 0) || (si > 39)) + return; + + if (var_6 > si) { + if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17) { + do { + si--; + } while (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17); + si++; + if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di - 1) == 0) { + if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di + 1) != 0) + di++; + } else + di--; + warning("GOB2 Stub! sub_197A6(di (=%d), si (=%d), 0);", si, di); + } + } else { + if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17) { + do { + si++; + } while (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di) > 17); + si--; + if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di - 1) == 0) { + if (_vm->_util->readVariableByte(_dword_2F2A4 + si * 40 + di + 1) != 0) + di++; + } else + di--; + warning("GOB2 Stub! sub_197A6(di (=%d), si (=%d), 0);", si, di); + } + } + if (var_8 > var_C) { + if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17) { + do { + var_C--; + } while (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17); + var_C++; + if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) == 0) { + if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) != 0) + var_A++; + } else + var_A--; + warning("GOB2 Stub! sub_197A6(var_A (=%d), var_C (=%d), 1);", var_A, var_C); + } + } else { + if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17) { + do { + var_C++; + } while (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) > 17); + var_C--; + if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) == 0) { + if (_vm->_util->readVariableByte(_dword_2F2A4 + var_C * 40 + var_A) != 0) + var_A++; + } else + var_A--; + warning("GOB2 Stub! sub_197A6(var_A (=%d), var_C (=%d), 1);", var_A, var_C); + } + } +} + } // End of namespace Gob diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h index 858bf247ae..2a43add91a 100644 --- a/engines/gob/goblin.h +++ b/engines/gob/goblin.h @@ -46,6 +46,12 @@ public: int16 sndFrame; // +Eh } GCC_PACK; + struct Gob2_State { + int16 animation; + int16 layer; + int16 field_4; + }; + typedef Gob_State *Gob_PState; typedef Gob_PState Gob_StateLine[6]; @@ -177,19 +183,28 @@ public: int16 _positionedGob; char _noPick; + // GOB2: + int16 _soundSlotsCount; + int16 _soundSlots[60]; + int16 _word_2F9C0; + int16 _word_2F9BE; + int16 _word_2F9BC; + int16 _word_2F9BA; + int16 _dword_2F9B6; // index into the variables array + int16 _dword_2F9B2; // index into the variables array + char *_dword_2F2A4; // index into the variables array + // Functions char rotateState(int16 from, int16 to); void playSound(Snd::SoundDesc * snd, int16 repCount, int16 freq); void drawObjects(void); void animateObjects(void); - void placeObject(Gob_Object * objDesc, char animated); int16 getObjMaxFrame(Gob_Object * obj); int16 objIntersected(Gob_Object * obj1, Gob_Object * obj2); void setMultStates(Gob_Object * gobDesc); int16 nextLayer(Gob_Object * gobDesc); void showBoredom(int16 gobIndex); void switchGoblin(int16 index); - void freeObjects(void); void zeroObjects(void); void freeAllObjects(void); void loadObjects(char *source); @@ -203,7 +218,14 @@ public: int16 treatItem(int16 action); int16 doMove(Gob_Object *gobDesc, int16 cont, int16 action); + void sub_19BD3(void); + + virtual void placeObject(Gob_Object * objDesc, char animated, + int16 index, int16 x, int16 y, int16 state) = 0; + virtual void freeObjects(void) = 0; + Goblin(GobEngine *vm); + virtual ~Goblin() {}; protected: int16 _rotStates[4][4]; @@ -226,6 +248,26 @@ protected: void moveAdvance(Gob_Object *gobDesc, int16 nextAct, int16 framesCount); }; +class Goblin_v1 : public Goblin { +public: + virtual void placeObject(Gob_Object * objDesc, char animated, + int16 index, int16 x, int16 y, int16 state); + virtual void freeObjects(void); + + Goblin_v1(GobEngine *vm); + virtual ~Goblin_v1() {}; +}; + +class Goblin_v2 : public Goblin_v1 { +public: + virtual void placeObject(Gob_Object * objDesc, char animated, + int16 index, int16 x, int16 y, int16 state); + virtual void freeObjects(void); + + Goblin_v2(GobEngine *vm); + virtual ~Goblin_v2() {}; +}; + } // End of namespace Gob #endif /* __GOBLIN_H */ diff --git a/engines/gob/goblin_v1.cpp b/engines/gob/goblin_v1.cpp new file mode 100644 index 0000000000..234cc778d9 --- /dev/null +++ b/engines/gob/goblin_v1.cpp @@ -0,0 +1,140 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 Ivan Dubrov + * Copyright (C) 2004-2006 The ScummVM project + * + * 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/goblin.h" +#include "gob/scenery.h" + +namespace Gob { + +Goblin_v1::Goblin_v1(GobEngine *vm) : Goblin(vm) { +} + +void Goblin_v1::freeObjects(void) { + int16 i; + int16 state; + int16 col; + + for (i = 0; i < 16; i++) { + if (_soundData[i] == 0) + continue; + + _vm->_snd->freeSoundDesc(_soundData[i]); + _soundData[i] = 0; + } + + for (i = 0; i < 4; i++) { + if (_goblins[i] == 0) + continue; + + _goblins[i]->stateMach = _goblins[i]->realStateMach; + + for (state = 0; state < 40; state++) { + for (col = 0; col < 6; col++) { + delete _goblins[i]->stateMach[state][col]; + _goblins[i]->stateMach[state][col] = 0; + } + } + + if (i == 3) { + for (state = 40; state < 70; state++) { + delete _goblins[3]->stateMach[state][0]; + _goblins[3]->stateMach[state][0] = 0; + } + } + + delete[] _goblins[i]->stateMach; + delete _goblins[i]; + _goblins[i] = 0; + } + + for (i = 0; i < 20; i++) { + if (_objects[i] == 0) + continue; + + _objects[i]->stateMach = _objects[i]->realStateMach; + + for (state = 0; state < 40; state++) { + for (col = 0; col < 6; col++) { + delete _objects[i]->stateMach[state][col]; + _objects[i]->stateMach[state][col] = 0; + } + } + + delete[] _objects[i]->stateMach; + delete _objects[i]; + _objects[i] = 0; + } +} + +void Goblin_v1::placeObject(Gob_Object *objDesc, char animated, + int16 index, int16 x, int16 y, int16 state) { + int16 layer; + + if (objDesc->stateMach[objDesc->state][0] != 0) { + objDesc->animation = + objDesc->stateMach[objDesc->state][0]->animation; + + objDesc->noTick = 0; + objDesc->toRedraw = 1; + objDesc->doAnim = animated; + + objDesc->maxTick = 1; + objDesc->tick = 1; + objDesc->curFrame = 0; + objDesc->type = 0; + objDesc->actionStartState = 0; + objDesc->nextState = -1; + objDesc->multState = -1; + objDesc->stateColumn = 0; + objDesc->curLookDir = 0; + objDesc->visible = 1; + objDesc->pickable = 0; + objDesc->unk14 = 0; + + objDesc->relaxTime = _vm->_util->getRandom(30); + + layer = objDesc->stateMach[objDesc->state][0]->layer; + _vm->_scenery->updateAnim(layer, 0, objDesc->animation, 0, + objDesc->xPos, objDesc->yPos, 0); + + objDesc->order = _vm->_scenery->_toRedrawBottom / 24 + 3; + + objDesc->left = objDesc->xPos; + objDesc->right = objDesc->xPos; + objDesc->dirtyLeft = objDesc->xPos; + objDesc->dirtyRight = objDesc->xPos; + + objDesc->top = objDesc->yPos; + objDesc->bottom = objDesc->yPos; + objDesc->dirtyTop = objDesc->yPos; + objDesc->dirtyBottom = objDesc->yPos; + + _vm->_util->listInsertBack(_objList, objDesc); + } +} + +} // End of namespace Gob diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp new file mode 100644 index 0000000000..724361ff4a --- /dev/null +++ b/engines/gob/goblin_v2.cpp @@ -0,0 +1,105 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 Ivan Dubrov + * Copyright (C) 2004-2006 The ScummVM project + * + * 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/goblin.h" +#include "gob/mult.h" +#include "gob/game.h" +#include "gob/scenery.h" + +namespace Gob { + +Goblin_v2::Goblin_v2(GobEngine *vm) : Goblin_v1(vm) { + _gobsCount = -1; +} + +void Goblin_v2::freeObjects(void) { + int i; + + if (_gobsCount < 0) + return; + + for (i = 0; i < _gobsCount; i++) { + delete[] _vm->_mult->_objects[i].goblinStates[0]; + delete[] _vm->_mult->_objects[i].goblinStates; + } + for (i = 0; i < _vm->_goblin->_soundSlotsCount; i++) + if ((_vm->_goblin->_soundSlots[i] & 0x8000) == 0) + _vm->_game->freeSoundSlot(_vm->_goblin->_soundSlots[i]); +// delete[] off_2F2AB; + _gobsCount = -1; +} + +void Goblin_v2::placeObject(Gob_Object *objDesc, char animated, + int16 index, int16 x, int16 y, int16 state) { + Mult::Mult_Object *obj; + Mult::Mult_AnimData *objAnim; + int16 layer; + int16 animation; + + obj = &_vm->_mult->_objects[index]; + objAnim = obj->pAnimData; + + obj->goblinX = x; + obj->goblinY = y; + objAnim->order = y; + + if (state == -1) { + objAnim->frame = 0; + objAnim->isPaused = 0; + objAnim->isStatic = 0; + objAnim->newCycle = 0; + _vm->_scenery->updateAnim(objAnim->layer, 0, objAnim->animation, 0, + *obj->pPosX, *obj->pPosY, 0); + if (_vm->_mult->_word_2CC86 == 0) + *obj->pPosY = (y + 1) * _vm->_mult->_word_2F2AF; // - (_vm->_scenery->_animBottom - _vm->scenery->_animTop); + else + *obj->pPosY = ((y + 1) / 2) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->scenery->_animTop); + *obj->pPosX = x * _vm->_mult->_word_2F2B1; + } else { + if (obj->goblinStates[state] != 0) { + layer = obj->goblinStates[state][0].layer; + animation = obj->goblinStates[state][0].animation; + objAnim->state = state; + objAnim->layer = layer; + objAnim->animation = animation; + objAnim->frame = 0; + objAnim->isPaused = 0; + objAnim->isStatic = 0; + objAnim->newCycle = _vm->_scenery->_animations[animation].layers[layer]->framesCount; + _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); + if (_vm->_mult->_word_2CC86 == 0) + *obj->pPosY = (y + 1) * _vm->_mult->_word_2F2AF; // - (_vm->_scenery->_animBottom - _vm->scenery->_animTop); + else + *obj->pPosY = ((y + 1) / 2) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->scenery->_animTop); + *obj->pPosX = x * _vm->_mult->_word_2F2B1; + warning("GOB2 Stub! sub_FE1D(obj"); + } else + warning("GOB2 Stub! sub_FE1D(obj"); + } +} + +} // End of namespace Gob diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index 1bfd0aadb5..c411a2430f 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -144,7 +144,7 @@ memBlocks = word ptr -2*/ _palDesc->unused2 = _vm->_draw->_unusedPalette2; _vm->_video->setFullPalette(_palDesc); - for (i = 0; i < 4; i++) + for (i = 0; i < 8; i++) _vm->_draw->_fonts[i] = 0; handle = _vm->_dataio->openData("intro.inf"); @@ -167,7 +167,7 @@ memBlocks = word ptr -2*/ infEnd = infBuf + _vm->_dataio->getDataSize("intro.inf"); for (i = 0; i < 4; i++, infPtr++) { - for (j = 0; *infPtr >= ' ' && infPtr != infEnd; + for (j = 0; infPtr < infEnd && *infPtr >= ' '; j++, infPtr++) buffer[j] = *infPtr; diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index ed51ab7893..69787ae601 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -40,11 +40,18 @@ namespace Gob { Inter::Inter(GobEngine *vm) : _vm(vm) { + int i; + _terminate = false; _breakFlag = false; - _animPalLowIndex = 0; - _animPalHighIndex = 0; - _animPalDir = 0; + + for (i = 0; i < 8; i++) + { + _animPalLowIndex[i] = 0; + _animPalHighIndex[i] = 0; + _animPalDir[i] = 0; + } + _soundEndTimeKey = 0; _soundStopVal = 0; _breakFromLevel = 0; @@ -96,34 +103,6 @@ char Inter::evalBoolResult() { return 0; } -void Inter::animPalette(void) { - int16 i; - Video::Color col; - - if (_animPalDir == 0) - return; - - _vm->_video->waitRetrace(_vm->_global->_videoMode); - - if (_animPalDir == -1) { - col = _vm->_draw->_vgaSmallPalette[_animPalLowIndex]; - - for (i = _animPalLowIndex; i < _animPalHighIndex; i++) - _vm->_draw->_vgaSmallPalette[i] = _vm->_draw->_vgaSmallPalette[i + 1]; - - _vm->_draw->_vgaSmallPalette[_animPalHighIndex] = col; - } else { - col = _vm->_draw->_vgaSmallPalette[_animPalHighIndex]; - for (i = _animPalHighIndex; i > _animPalLowIndex; i--) - _vm->_draw->_vgaSmallPalette[i] = _vm->_draw->_vgaSmallPalette[i - 1]; - - _vm->_draw->_vgaSmallPalette[_animPalLowIndex] = col; - } - - _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaSmallPalette; - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); -} - void Inter::funcBlock(int16 retFlag) { char cmdCount; int16 counter; @@ -305,7 +284,7 @@ void Inter::initControlVars(void) { _breakFlag = false; _terminate = false; - _animPalDir = 0; + _animPalDir[0] = 0; _soundEndTimeKey = 0; } diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 5f99cc154a..2ae07da874 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -37,9 +37,9 @@ namespace Gob { class Inter { public: - int16 _animPalLowIndex; - int16 _animPalHighIndex; - int16 _animPalDir; + int16 _animPalLowIndex[8]; + int16 _animPalHighIndex[8]; + int16 _animPalDir[8]; uint32 _soundEndTimeKey; int16 _soundStopVal; char _terminate; @@ -53,7 +53,6 @@ public: char evalExpr(int16 *pRes); char evalBoolResult(void); - void animPalette(void); void funcBlock(int16 retFlag); void storeKey(int16 key); void checkSwitchTable(char **ppExec); @@ -78,6 +77,7 @@ protected: virtual const char *getOpcodeFuncDesc(byte i, byte j) = 0; virtual const char *getOpcodeGoblinDesc(int i) = 0; virtual void loadMult(void) = 0; + virtual void animPalette(void) = 0; }; class Inter_v1 : public Inter { @@ -116,6 +116,7 @@ protected: virtual const char *getOpcodeFuncDesc(byte i, byte j); virtual const char *getOpcodeGoblinDesc(int i); virtual void loadMult(void); + virtual void animPalette(void); void o1_loadMult(void); void o1_playMult(void); @@ -307,21 +308,30 @@ protected: virtual const char *getOpcodeFuncDesc(byte i, byte j); virtual const char *getOpcodeGoblinDesc(int i); virtual void loadMult(void); + virtual void animPalette(void); - void o2_drawStub(void) { warning("Gob2 stub"); } + void o2_drawStub(void) { error("Gob2 stub"); } void o2_totSub(void); + void o2_switchTotSub(void); void o2_stub0x52(void); - void o2_stub0x53(void); void o2_stub0x54(void); - void o2_stub0x56(void); void o2_stub0x80(void); + void o2_stub0x82(void); + void o2_stub0x83(void); + void o2_stub0x85(void); void o2_renderStatic(void); + bool o2_animPalInit(char &cmdCount, int16 &counter, int16 &retFlag); + bool o2_playSound(char &cmdCount, int16 &counter, int16 &retFlag); bool o2_goblinFunc(char &cmdCount, int16 &counter, int16 &retFlag); bool o2_evaluateStore(char &cmdCount, int16 &counter, int16 &retFlag); bool o2_palLoad(char &cmdCount, int16 &counter, int16 &retFlag); bool o2_loadTot(char &cmdCount, int16 &counter, int16 &retFlag); bool o2_freeSprite(char &cmdCount, int16 &counter, int16 &retFlag); bool o2_loadSound(char &cmdCount, int16 &counter, int16 &retFlag); + void o2_loadMapObjects(void); + void o2_freeGoblins(void); + void o2_writeGoblinPos(void); + void o2_placeGoblin(void); void o2_multSub(void); void o2_setRenderFlags(void); void o2_initMult(void); diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 59785fc46e..9e6b574f67 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -754,9 +754,9 @@ bool Inter_v1::o1_printText(char &cmdCount, int16 &counter, int16 &retFlag) { } bool Inter_v1::o1_animPalInit(char &cmdCount, int16 &counter, int16 &retFlag) { - _animPalDir = load16(); - _animPalLowIndex = _vm->_parse->parseValExpr(); - _animPalHighIndex = _vm->_parse->parseValExpr(); + _animPalDir[0] = load16(); + _animPalLowIndex[0] = _vm->_parse->parseValExpr(); + _animPalHighIndex[0] = _vm->_parse->parseValExpr(); return false; } @@ -1199,6 +1199,7 @@ bool Inter_v1::o1_playComposition(char &cmdCount, int16 &counter, int16 &retFlag } bool Inter_v1::o1_stopSound(char &cmdCount, int16 &counter, int16 &retFlag) { + _vm->_music->stopPlay(); _vm->_snd->stopSound(_vm->_parse->parseValExpr()); _soundEndTimeKey = 0; return false; @@ -2764,4 +2765,32 @@ void Inter_v1::storeMouse(void) { WRITE_VAR(4, _vm->_game->_mouseButtons); } +void Inter_v1::animPalette(void) { + int16 i; + Video::Color col; + + if (_animPalDir[0] == 0) + return; + + _vm->_video->waitRetrace(_vm->_global->_videoMode); + + if (_animPalDir[0] == -1) { + col = _vm->_draw->_vgaSmallPalette[_animPalLowIndex[0]]; + + for (i = _animPalLowIndex[0]; i < _animPalHighIndex[0]; i++) + _vm->_draw->_vgaSmallPalette[i] = _vm->_draw->_vgaSmallPalette[i + 1]; + + _vm->_draw->_vgaSmallPalette[_animPalHighIndex[0]] = col; + } else { + col = _vm->_draw->_vgaSmallPalette[_animPalHighIndex[0]]; + for (i = _animPalHighIndex[0]; i > _animPalLowIndex[0]; i--) + _vm->_draw->_vgaSmallPalette[i] = _vm->_draw->_vgaSmallPalette[i - 1]; + + _vm->_draw->_vgaSmallPalette[_animPalLowIndex[0]] = col; + } + + _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaSmallPalette; + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); +} + } // End of namespace Gob diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 27448e80a9..b09dbf61fc 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -37,6 +37,8 @@ #include "gob/cdrom.h" #include "gob/palanim.h" #include "gob/anim.h" +#include "gob/music.h" +#include "gob/map.h" namespace Gob { @@ -204,7 +206,7 @@ void Inter_v2::setupOpcodes(void) { {NULL, ""}, /* 40 */ OPCODE(o2_totSub), - OPCODE(o2_drawStub), + OPCODE(o2_switchTotSub), OPCODE(o2_drawStub), OPCODE(o2_drawStub), /* 44 */ @@ -223,14 +225,14 @@ void Inter_v2::setupOpcodes(void) { {NULL, ""}, {NULL, ""}, /* 50 */ - OPCODE(o2_drawStub), - OPCODE(o2_drawStub), + OPCODE(o2_loadMapObjects), + OPCODE(o2_freeGoblins), OPCODE(o2_stub0x52), - OPCODE(o2_stub0x53), + OPCODE(o2_writeGoblinPos), /* 54 */ OPCODE(o2_stub0x54), OPCODE(o2_drawStub), - OPCODE(o2_stub0x56), + OPCODE(o2_placeGoblin), {NULL, ""}, /* 58 */ {NULL, ""}, @@ -285,11 +287,11 @@ void Inter_v2::setupOpcodes(void) { /* 80 */ OPCODE(o2_stub0x80), OPCODE(o2_drawStub), - OPCODE(o2_drawStub), - OPCODE(o2_drawStub), + OPCODE(o2_stub0x82), + OPCODE(o2_stub0x83), /* 84 */ OPCODE(o2_drawStub), - OPCODE(o2_drawStub), + OPCODE(o2_stub0x85), OPCODE(o2_drawStub), OPCODE(o2_drawStub), /* 88 */ @@ -474,7 +476,7 @@ void Inter_v2::setupOpcodes(void) { OPCODE(o1_keyFunc), OPCODE(o1_capturePush), OPCODE(o1_capturePop), - OPCODE(o1_animPalInit), + OPCODE(o2_animPalInit), /* 18 */ {NULL, ""}, {NULL, ""}, @@ -516,7 +518,7 @@ void Inter_v2::setupOpcodes(void) { OPCODE(o1_invalidate), OPCODE(o1_setBackDelta), /* 38 */ - OPCODE(o1_playSound), + OPCODE(o2_playSound), OPCODE(o1_stopSound), OPCODE(o2_loadSound), OPCODE(o1_freeSoundSlot), @@ -718,17 +720,6 @@ void Inter_v2::o2_stub0x52(void) { warning("STUB: Gob2 drawOperation 0x52 (%d %d %d)", expr1, expr2, expr3); } -void Inter_v2::o2_stub0x53(void) { - int16 var1 = _vm->_parse->parseVarIndex() >> 2; - int16 var2 = _vm->_parse->parseVarIndex() >> 2; - int16 index = _vm->_parse->parseValExpr(); - - warning("STUB: Gob2 drawOperation 0x53 (%d %d %d)", var1, var2, index); - -// WRITE_VAR(var1, _vm->_mult->_objects[index].field_1A); -// WRITE_VAR(var2, _vm->_mult->_objects[index].field_1B); -} - void Inter_v2::o2_stub0x54(void) { int16 index = _vm->_parse->parseValExpr(); @@ -737,15 +728,6 @@ void Inter_v2::o2_stub0x54(void) { // _vm->_mult->_objects[index].pAnimData->field_12 = 4; } -void Inter_v2::o2_stub0x56(void) { - int16 expr1 = _vm->_parse->parseValExpr(); - int16 expr2 = _vm->_parse->parseValExpr(); - int16 expr3 = _vm->_parse->parseValExpr(); - int16 expr4 = _vm->_parse->parseValExpr(); - - warning("STUB: Gob2 drawOperation 0x56 (%d %d %d %d)", expr1, expr2, expr3, expr4); -} - void Inter_v2::o2_stub0x80(void) { int16 start; int16 videoMode; @@ -817,156 +799,194 @@ void Inter_v2::o2_stub0x80(void) { } } -int16 Inter_v2::loadSound(int16 search) { - int16 id; - int16 slot; -/* int i; - int8 var_7; - char *pointer; - char sndfile[14]; +void Inter_v2::o2_stub0x82(void) { + int16 expr; - char *dword_2EBF0[60]; - int16 word_2EAFE[60]; - int8 byte_2EB8A[60]; + expr = _vm->_parse->parseValExpr(); - for (i = 0; i < 60; i++) - dword_2EBF0[i] = 0;*/ + if (expr == -1) { + if (_vm->_game->_byte_2FC9B != 0) + _vm->_game->_byte_2FC9B = 1; + _vm->_parse->parseValExpr(); + WRITE_VAR(2, _vm->_game->_word_2FC9E); + WRITE_VAR(3, _vm->_game->_word_2FC9C); + } else { + _vm->_game->_word_2FC9E = expr; + _vm->_game->_word_2FC9C = _vm->_parse->parseValExpr(); + } +/* if (_vm->_game->_off_2E51B != 0) + warning("GOB2 Stub! _vid_setPixelShift(_vm->_game->_word_2FC9E, _vm->_game->_word_2FC9C + 200 - _vm->_game->_word_2E51F)"); + else + warning("GOB2 Stub! _vid_setPixelShift(_vm->_game->_word_2FC9E, _vm->_game->_word_2FC9C);");*/ +} - warning("STUB: loadSound()"); +// some sub +void Inter_v2::o2_stub0x83(void) { + char dest[128]; + int16 expr1; + int16 expr2; + int16 expr3; + int16 expr4; + int16 expr5; + int16 expr6; + int16 expr7; + int16 expr8; + + evalExpr(0); + strcpy(dest, _vm->_global->_inter_resStr); + expr1 = _vm->_parse->parseValExpr(); + expr2 = _vm->_parse->parseValExpr(); + expr3 = _vm->_parse->parseValExpr(); + expr4 = _vm->_parse->parseValExpr(); + expr5 = _vm->_parse->parseValExpr(); + expr6 = _vm->_parse->parseValExpr(); + expr7 = _vm->_parse->parseValExpr(); + expr8 = _vm->_parse->parseValExpr(); + + warning("STUB: Gob2 drawOperation 0x83 (\"%s\" %d %d %d %d %d %d %d %d)", dest, expr1, expr2, expr3, expr4, expr5, expr6, expr7, expr8); +} - slot = 0; - if (search == 0) { - slot = _vm->_parse->parseValExpr(); - } - id = load16(); +void Inter_v2::o2_stub0x85(void) { + char dest[32]; -// warning("==> %d %d", slot, id); + evalExpr(0); + strcpy(dest, _vm->_global->_inter_resStr); + strcat(dest, ".ITK"); - if (id == -1) - _vm->_global->_inter_execPtr += 9; + warning("STUB: Gob2 drawOperation 0x85 (\"%s\")", dest); + _vm->_dataio->openDataFile(dest); +} - return slot; +int16 Inter_v2::loadSound(int16 search) { + int16 id; // si + int16 slot; // di + int32 i; + bool isADL; + char sndfile[14]; + char *extData; + char *dataPtr; + Snd::SoundDesc *soundDesc; + + memset(sndfile, 0, 14 * sizeof(char)); -/* var_7 = 0; + isADL = false; if (search == 0) { slot = _vm->_parse->parseValExpr(); if (slot < 0) { - var_7 = 1; + isADL = true; slot = -slot; } id = load16(); - } - else { - // loc_961D + } else { id = load16(); for (slot = 0; slot < 60; slot++) - if ((dword_2EBF0[slot] != 0) && (word_2EAFE[slot] = id)) + if ((_vm->_game->_soundSamples[slot] != 0) && (_vm->_game->_soundIds[slot] == id)) return slot | 0x8000; for (slot = 59; slot >= 0; slot--) - if (dword_2EBF0[slot] == 0) break; - + if (_vm->_game->_soundSamples[slot] == 0) break; } - - if (dword_2EBF0[slot] != 0) + + if (_vm->_game->_soundSamples[slot] != 0) _vm->_game->freeSoundSlot(slot); - word_2EAFE[slot] = id; + _vm->_game->_soundIds[slot] = id; - if (id == -1) { + if (id == -1) { // loc_969D strcpy(sndfile, _vm->_global->_inter_execPtr); _vm->_global->_inter_execPtr += 9; - if (var_7 == 0) { - // loc_96EB + if (!isADL) { strcat(sndfile, ".SND"); -// dword_2EBF0[slot] = sub_1F5D0(sndfile); - } - else { + _vm->_game->_soundSamples[slot] = _vm->_game->loadSND(sndfile, 3); + } else { strcat(sndfile, ".ADL"); - dword_2EBF0[slot] = _vm->_dataio->getData(sndfile); + // TODO: This is very ugly + _vm->_game->_soundSamples[slot] = (Snd::SoundDesc *) _vm->_dataio->getData(sndfile); } - byte_2EB8A[slot] = 2; - // loc_969D - } - else { - // loc_9735 - if (id >= 30000) { - // loc_973E - if ((var_7 == 0) && - (_vm->_global->_soundFlags & 0x14) && - (_vm->_game->_totFileData[0x29] >= 51)) { - // loc_9763 - if (_vm->_global->_soundFlags & 0x14) { - // loc_976E -// var_E = new char[16]; - if (_vm->_inter->_terminate) - return slot; - pointer = _vm->_game->loadExtData(id, NULL, NULL); - if (pointer == NULL) { -// delete[] var_E; - return slot; - } - // loc_97C5 -// var_E->pointer = pointer+6; -// var_E->0x0C = pointer[4] << 8 + pointer[5]; - // ... -// dword_2EBF0[slot] = var_E; - delete[] pointer; + _vm->_game->_soundTypes[slot] = 2; + } else { // loc_9735 + if (id >= 30000) { // loc_973E + if (!isADL && (_vm->_game->_totFileData[0x29] >= 51)) { // loc_9763 + if (_vm->_inter->_terminate != 0) return slot; - } - else { - // loc_9A59 + soundDesc = new Snd::SoundDesc; + extData = _vm->_game->loadExtData(id, 0, 0); + if (extData == 0) { + delete soundDesc; return slot; } + soundDesc->data = extData + 6; + soundDesc->frequency = (extData[4] << 8) + extData[5]; + soundDesc->size = (extData[1] << 16) + (extData[2] << 8) + extData[3]; + soundDesc->flag = 0; + if (soundDesc->frequency < 4700) + soundDesc->frequency = 4700; + soundDesc->frequency = -soundDesc->frequency; + for (i = 0, dataPtr = soundDesc->data; i < soundDesc->size; i++, dataPtr++) + *dataPtr ^= 0x80; + _vm->_game->_soundTypes[slot] = 4; + _vm->_game->_soundSamples[slot] = soundDesc; + } else { // loc_99BC + extData = _vm->_game->loadExtData(id, 0, 0); + if (extData == 0) + return slot; + _vm->_game->_soundTypes[slot] = 1; + if (!isADL) + _vm->_game->loadSound(slot, extData); + else + // TODO: This is very ugly + _vm->_game->_soundSamples[slot] = (Snd::SoundDesc *) extData; } - else { - // loc_99BC - pointer = _vm->_game->loadExtData(id, NULL, NULL); - // ... - delete[] pointer; - return slot; - } - } - else { - // loc_9A13 -// pointer = _vm->_game->loadTotResource(id); - return slot; + } else { // loc_9A13 + extData = _vm->_game->loadTotResource(id); + if (!isADL) + _vm->_game->loadSound(slot, extData); + else + // TODO: This is very ugly + _vm->_game->_soundSamples[slot] = (Snd::SoundDesc *) extData; } } + // loc_9A4E - if (var_7 != 0) - byte_2EB8A[slot] |= 8; + if (isADL) + _vm->_game->_soundTypes[slot] |= 8; - if (dword_2EBF0[slot]) - delete[] dword_2EBF0[slot]; + return slot; +} - return slot;*/ - -/* char *dataPtr; - int16 id; +void Inter_v2::o2_loadMapObjects(void) { + _vm->_map->loadMapObjects(0); +} - if (slot == -1) - slot = _vm->_parse->parseValExpr(); +void Inter_v2::o2_freeGoblins(void) { + _vm->_goblin->freeObjects(); +} - id = load16(); - if (id == -1) { - _vm->_global->_inter_execPtr += 9; - return; - } +void Inter_v2::o2_placeGoblin(void) { + int16 index; + int16 x; + int16 y; + int16 state; - if (id >= 30000) { - dataPtr = _vm->_game->loadExtData(id, 0, 0); - _vm->_game->_soundFromExt[slot] = 1; - } else { - dataPtr = _vm->_game->loadTotResource(id); - _vm->_game->_soundFromExt[slot] = 0; - } + index = _vm->_parse->parseValExpr(); + x = _vm->_parse->parseValExpr(); + y = _vm->_parse->parseValExpr(); + state = _vm->_parse->parseValExpr(); - warning("STUB: loadSound()"); - return; + _vm->_goblin->placeObject(0, 0, index, x, y, state); +} - _vm->_game->loadSound(slot, dataPtr);*/ +void Inter_v2::o2_writeGoblinPos(void) { + int16 var1; + int16 var2; + int16 index; + + var1 = _vm->_parse->parseVarIndex() >> 2; + var2 = _vm->_parse->parseVarIndex() >> 2; + index = _vm->_parse->parseValExpr(); + WRITE_VAR(var1, _vm->_mult->_objects[index].goblinX); + WRITE_VAR(var2, _vm->_mult->_objects[index].goblinY); } void Inter_v2::o2_multSub(void) { @@ -984,9 +1004,12 @@ void Inter_v2::o2_renderStatic(void) { void Inter_v2::loadMult(void) { int16 val; - int16 objIndex; + int16 objIndex; // si int16 i; + int16 animation; char *lmultData; + Mult::Mult_Object *obj; + Mult::Mult_AnimData *objAnim; debugC(4, DEBUG_GAMEFLOW, "Inter_v2::loadMult(): Loading..."); @@ -998,36 +1021,142 @@ void Inter_v2::loadMult(void) { lmultData = (char *)_vm->_mult->_objects[objIndex].pAnimData; for (i = 0; i < 11; i++) { - if (*_vm->_global->_inter_execPtr != 99) { - val = _vm->_parse->parseValExpr(); - lmultData[i] = val; - } else + if (*_vm->_global->_inter_execPtr != 99) + lmultData[i] = _vm->_parse->parseValExpr(); + else _vm->_global->_inter_execPtr++; } - warning("GOB2 Stub! Inter_v2::loadMult()"); + if (_vm->_mult->_objects[objIndex].pAnimData->animType == 100) { + if (_vm->_goblin->_gobsCount >= 0) { + obj = &_vm->_mult->_objects[objIndex]; + objAnim = obj->pAnimData; + + val = *obj->pPosX % 256; + obj->field_1C = val; + obj->field_1E = val; + obj->goblinX = val; + val = *obj->pPosY % 256; + obj->field_1D = val; + obj->field_1F = val; + obj->goblinY = val; + *obj->pPosX *= _vm->_mult->_word_2F2B1; + objAnim->field_15 = objAnim->unknown; + objAnim->field_E = -1; + objAnim->field_F = -1; + objAnim->field_12 = 0; + objAnim->state = objAnim->layer; + objAnim->layer = obj->goblinStates[objAnim->state][0].layer; + objAnim->animation = obj->goblinStates[objAnim->state][0].animation; + animation = objAnim->animation; + _vm->_scenery->updateAnim(objAnim->state, 0, 0, 0, *obj->pPosX, *obj->pPosY, 0); + if (_vm->_mult->_word_2CC86 == 0) { + *obj->pPosY = (obj->goblinY + 1) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) + } else { + *obj->pPosY = (obj->goblinY + 1) * _vm->_mult->_word_2F2AF; //- (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (obj->goblinY + 1) / 2; + } + *obj->pPosX = obj->goblinX * _vm->_mult->_word_2F2B1; + } + } + if (_vm->_mult->_objects[objIndex].pAnimData->animType == 101) { + if (_vm->_goblin->_gobsCount >= 0) { + obj = &_vm->_mult->_objects[objIndex]; + objAnim = obj->pAnimData; + + objAnim->field_E = -1; + objAnim->field_F = -1; + objAnim->state = objAnim->layer; + objAnim->layer = obj->goblinStates[objAnim->state][0].layer; + objAnim->animation = obj->goblinStates[objAnim->state][0].animation; + if ((*obj->pPosX == 1000) && (*obj->pPosY == 1000)) { + *obj->pPosX = _vm->_scenery->_animations[objAnim->animation].layers[objAnim->state]->posX; + *obj->pPosY = _vm->_scenery->_animations[objAnim->animation].layers[objAnim->state]->posY; + } + _vm->_scenery->updateAnim(objAnim->state, 0, objAnim->animation, 0, *obj->pPosX, *obj->pPosY, 0); + } + } +} + +bool Inter_v2::o2_animPalInit(char &cmdCount, int16 &counter, int16 &retFlag) { + int16 index; + + index = load16(); + if (index > 0) { + index--; + _animPalLowIndex[index] = _vm->_parse->parseValExpr(); + _animPalHighIndex[index] = _vm->_parse->parseValExpr(); + _animPalDir[index] = 1; + } else if (index == 0) { + memset(_animPalDir, 0, 8 * sizeof(int16)); + _vm->_parse->parseValExpr(); + _vm->_parse->parseValExpr(); + } else { + index = -index - 1; + _animPalLowIndex[index] = _vm->_parse->parseValExpr(); + _animPalHighIndex[index] = _vm->_parse->parseValExpr(); + _animPalDir[index] = -1; + } + return false; +} + +bool Inter_v2::o2_playSound(char &cmdCount, int16 &counter, int16 &retFlag) { + int16 frequency; + int16 freq2; + int16 repCount; // di + int16 index; // si + + index = _vm->_parse->parseValExpr(); + repCount = _vm->_parse->parseValExpr(); + frequency = _vm->_parse->parseValExpr(); + + _soundEndTimeKey = 0; + if (_vm->_game->_soundSamples[index] == 0) + return false; + + if (repCount < 0) { + if (_vm->_global->_soundFlags < 2) + return false; + + repCount = -repCount; + _soundEndTimeKey = _vm->_util->getTimeKey(); + + if (frequency == 0) + freq2 = _vm->_game->_soundSamples[index]->frequency; + else + freq2 = frequency; + _soundStopVal = + (10 * (_vm->_game->_soundSamples[index]->size / 2)) / freq2; + _soundEndTimeKey += + ((_vm->_game->_soundSamples[index]->size * repCount - + _vm->_game->_soundSamples[index]->size / 2) * 1000) / freq2; + } + // loc_E2F3 + if (_vm->_game->_soundTypes[index] & 8) { + _vm->_music->loadFromMemory((byte *) _vm->_game->_soundSamples[index]); + _vm->_music->setRepeating(repCount - 1); + _vm->_music->startPlay(); + } else { + _vm->_snd->stopSound(0); + _vm->_snd->playSample(_vm->_game->_soundSamples[index], repCount, frequency); + } + + return false; } bool Inter_v2::o2_goblinFunc(char &cmdCount, int16 &counter, int16 &retFlag) { int16 cmd; - int16 word_2F9C0; - int16 word_2F9BE; - int16 word_2F9BC; - int16 word_2F9BA; - char *dword_2F9B6; - char *dword_2F9B2; cmd = load16(); _vm->_global->_inter_execPtr += 2; if (cmd == 100) { - word_2F9C0 = VAR(load16()); - word_2F9BE = VAR(load16()); - dword_2F9B6 = _vm->_global->_inter_variables + (load16() >> 2); - dword_2F9B2 = _vm->_global->_inter_variables + (load16() >> 2); - word_2F9BC = VAR(load16()); - word_2F9BA = VAR(load16()); - warning("GOB2 Stub! sub_19BD3()"); + _vm->_goblin->_word_2F9C0 = VAR(load16()); + _vm->_goblin->_word_2F9BE = VAR(load16()); + _vm->_goblin->_dword_2F9B6 = load16(); + _vm->_goblin->_dword_2F9B2 = load16(); + _vm->_goblin->_word_2F9BC = VAR(load16()); + _vm->_goblin->_word_2F9BA = VAR(load16()); + _vm->_goblin->sub_19BD3(); } else if (cmd != 101) { _vm->_global->_inter_execPtr -= 2; cmd = load16(); @@ -1569,6 +1698,16 @@ void Inter_v2::o2_totSub(void) { _vm->_game->totSub(flags, totFile); } +void Inter_v2::o2_switchTotSub(void) { + int16 index; + int16 skipPlay; + + index = load16(); + skipPlay = load16(); + + _vm->_game->switchTotSub(index, skipPlay); +} + void Inter_v2::storeMouse(void) { int16 x; int16 y; @@ -1586,4 +1725,40 @@ void Inter_v2::o2_setPickable(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Ob warning("GOB2 Stub! o2_setPickable"); } +void Inter_v2::animPalette(void) { + int16 i; + int16 j; + Video::Color col; + bool first; + + first = true; + for (j = 0; j < 8; j ++) { + if (_animPalDir[j] == 0) + continue; + + if (first) { + _vm->_video->waitRetrace(_vm->_global->_videoMode); + first = false; + } + + if (_animPalDir[j] == -1) { + col = _vm->_global->_pPaletteDesc->vgaPal[_animPalLowIndex[j]]; + + for (i = _animPalLowIndex[j]; i < _animPalHighIndex[j]; i++) + _vm->_draw->_vgaPalette[i] = _vm->_global->_pPaletteDesc->vgaPal[i]; + + _vm->_global->_pPaletteDesc->vgaPal[_animPalHighIndex[j]] = col; + } else { + col = _vm->_global->_pPaletteDesc->vgaPal[_animPalHighIndex[j]]; + for (i = _animPalHighIndex[j]; i > _animPalLowIndex[j]; i--) + _vm->_draw->_vgaPalette[i] = _vm->_global->_pPaletteDesc->vgaPal[i]; + + _vm->_global->_pPaletteDesc->vgaPal[_animPalLowIndex[j]] = col; + } + _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; + } + if (!first) + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); +} + } // End of namespace Gob diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp index 4e90e5f232..5333ee5219 100644 --- a/engines/gob/map.cpp +++ b/engines/gob/map.cpp @@ -440,314 +440,6 @@ void Map::loadItemToObject(void) { } } -void Map::loadMapObjects(char *avjFile) { - int16 i; - char avoName[128]; - int16 handle; - char item; - int16 soundCount; - int16 tmp; - char *savedPtr; - char *savedPtr2; - char *savedPtr3; - int16 state; - int16 col; - int32 flag; - Goblin::Gob_State *pState; - char buf[128]; - char sndNames[20][14]; - char *dataBuf; - int16 x; - int16 y; - int16 count2; - int16 count3; - - strcpy(avoName, _sourceFile); - strcat(avoName, ".avo"); - - handle = _vm->_dataio->openData(avoName); - if (handle >= 0) { - _loadFromAvo = 1; - _vm->_dataio->closeData(handle); - _avoDataPtr = _vm->_dataio->getData(avoName); - dataBuf = _avoDataPtr; - loadDataFromAvo((char *)_passMap, kMapHeight * kMapWidth); - - for (y = 0; y < kMapHeight; y++) { - for (x = 0; x < kMapWidth; x++) { - loadDataFromAvo(&item, 1); - _itemsMap[y][x] = item; - } - } - - for (i = 0; i < 40; i++) { - _wayPoints[i].x = loadFromAvo_LE_UINT16(); - _wayPoints[i].y = loadFromAvo_LE_UINT16(); - } - loadDataFromAvo((char *)_itemPoses, szMap_ItemPos * 20); - } else { - _loadFromAvo = 0; - _avoDataPtr = _vm->_dataio->getData(avjFile); - dataBuf = _avoDataPtr; - } - - _avoDataPtr += 32; - _avoDataPtr += 76; - _avoDataPtr += 4; - _avoDataPtr += 20; - - for (i = 0; i < 3; i++) { - tmp = loadFromAvo_LE_UINT16(); - _avoDataPtr += tmp * 14; - } - - soundCount = loadFromAvo_LE_UINT16(); - savedPtr = _avoDataPtr; - - _avoDataPtr += 14 * soundCount; - _avoDataPtr += 4; - _avoDataPtr += 24; - - count2 = loadFromAvo_LE_UINT16(); - count3 = loadFromAvo_LE_UINT16(); - - savedPtr2 = _avoDataPtr; - _avoDataPtr += count2 * 8; - - savedPtr3 = _avoDataPtr; - _avoDataPtr += count3 * 8; - - _vm->_goblin->_gobsCount = loadFromAvo_LE_UINT16(); - for (i = 0; i < _vm->_goblin->_gobsCount; i++) { - _vm->_goblin->_goblins[i] = new Goblin::Gob_Object; - - _vm->_goblin->_goblins[i]->xPos = READ_LE_UINT16(savedPtr2); - savedPtr2 += 2; - - _vm->_goblin->_goblins[i]->yPos = READ_LE_UINT16(savedPtr2); - savedPtr2 += 2; - - _vm->_goblin->_goblins[i]->order = READ_LE_UINT16(savedPtr2); - savedPtr2 += 2; - - _vm->_goblin->_goblins[i]->state = READ_LE_UINT16(savedPtr2); - savedPtr2 += 2; - - if (i == 3) - _vm->_goblin->_goblins[i]->stateMach = new Goblin::Gob_StateLine[70]; - else - _vm->_goblin->_goblins[i]->stateMach = new Goblin::Gob_StateLine[40]; - - uint32* tempstatedata = new uint32[40*6]; - for (state = 0; state < 40; ++state) { - for (col = 0; col < 6; ++col) { - tempstatedata[state*6+col] = READ_LE_UINT32(_avoDataPtr); - _avoDataPtr += 4; - } - } - _avoDataPtr += 160; - _vm->_goblin->_goblins[i]->multObjIndex = *_avoDataPtr; - _avoDataPtr += 2; - - _vm->_goblin->_goblins[i]->realStateMach = _vm->_goblin->_goblins[i]->stateMach; - for (state = 0; state < 40; state++) { - for (col = 0; col < 6; col++) { - if (tempstatedata[state*6+col] == 0) { - _vm->_goblin->_goblins[i]->stateMach[state][col] = 0; - continue; - } - - Goblin::Gob_State *tmpState = new Goblin::Gob_State; - _vm->_goblin->_goblins[i]->stateMach[state][col] = tmpState; - - tmpState->animation = loadFromAvo_LE_UINT16(); - tmpState->layer = loadFromAvo_LE_UINT16(); - _avoDataPtr += 8; - tmpState->unk0 = loadFromAvo_LE_UINT16(); - tmpState->unk1 = loadFromAvo_LE_UINT16(); - - _avoDataPtr += 2; - if (READ_LE_UINT32(_avoDataPtr) != 0) { - _avoDataPtr += 4; - tmpState->sndItem = loadFromAvo_LE_UINT16(); - } else { - _avoDataPtr += 6; - tmpState->sndItem = -1; - } - tmpState->freq = loadFromAvo_LE_UINT16(); - tmpState->repCount = loadFromAvo_LE_UINT16(); - tmpState->sndFrame = loadFromAvo_LE_UINT16(); - } - } - delete[] tempstatedata; - } - - pState = new Goblin::Gob_State; - _vm->_goblin->_goblins[0]->stateMach[39][0] = pState; - pState->animation = 0; - pState->layer = 98; - pState->unk0 = 0; - pState->unk1 = 0; - pState->sndItem = -1; - - pState = new Goblin::Gob_State; - _vm->_goblin->_goblins[1]->stateMach[39][0] = pState; - pState->animation = 0; - pState->layer = 99; - pState->unk0 = 0; - pState->unk1 = 0; - pState->sndItem = -1; - - pState = new Goblin::Gob_State; - _vm->_goblin->_goblins[2]->stateMach[39][0] = pState; - pState->animation = 0; - pState->layer = 100; - pState->unk0 = 0; - pState->unk1 = 0; - pState->sndItem = -1; - - _vm->_goblin->_goblins[2]->stateMach[10][0]->sndFrame = 13; - _vm->_goblin->_goblins[2]->stateMach[11][0]->sndFrame = 13; - _vm->_goblin->_goblins[2]->stateMach[28][0]->sndFrame = 13; - _vm->_goblin->_goblins[2]->stateMach[29][0]->sndFrame = 13; - - _vm->_goblin->_goblins[1]->stateMach[10][0]->sndFrame = 13; - _vm->_goblin->_goblins[1]->stateMach[11][0]->sndFrame = 13; - - for (state = 40; state < 70; state++) { - pState = new Goblin::Gob_State; - _vm->_goblin->_goblins[3]->stateMach[state][0] = pState; - _vm->_goblin->_goblins[3]->stateMach[state][1] = 0; - - pState->animation = 9; - pState->layer = state - 40; - pState->sndItem = -1; - pState->sndFrame = 0; - } - - _vm->_goblin->_objCount = loadFromAvo_LE_UINT16(); - for (i = 0; i < _vm->_goblin->_objCount; i++) { - _vm->_goblin->_objects[i] = new Goblin::Gob_Object; - - _vm->_goblin->_objects[i]->xPos = READ_LE_UINT16(savedPtr3); - savedPtr3 += 2; - - _vm->_goblin->_objects[i]->yPos = READ_LE_UINT16(savedPtr3); - savedPtr3 += 2; - - _vm->_goblin->_objects[i]->order = READ_LE_UINT16(savedPtr3); - savedPtr3 += 2; - - _vm->_goblin->_objects[i]->state = READ_LE_UINT16(savedPtr3); - savedPtr3 += 2; - - _vm->_goblin->_objects[i]->stateMach = new Goblin::Gob_StateLine[40]; - - uint32* tempstatedata = new uint32[40*6]; - for (state = 0; state < 40; ++state) { - for (col = 0; col < 6; ++col) { - tempstatedata[state*6+col] = READ_LE_UINT32(_avoDataPtr); - _avoDataPtr += 4; - } - } - _avoDataPtr += 160; - _vm->_goblin->_objects[i]->multObjIndex = *_avoDataPtr; - _avoDataPtr += 2; - - _vm->_goblin->_objects[i]->realStateMach = _vm->_goblin->_objects[i]->stateMach; - for (state = 0; state < 40; state++) { - for (col = 0; col < 6; col++) { - if (tempstatedata[state*6+col] == 0) { - _vm->_goblin->_objects[i]->stateMach[state][col] = 0; - continue; - } - - Goblin::Gob_State *tmpState = new Goblin::Gob_State; - _vm->_goblin->_objects[i]->stateMach[state][col] = tmpState; - - tmpState->animation = loadFromAvo_LE_UINT16(); - tmpState->layer = loadFromAvo_LE_UINT16(); - _avoDataPtr += 8; - tmpState->unk0 = loadFromAvo_LE_UINT16(); - tmpState->unk1 = loadFromAvo_LE_UINT16(); - - _avoDataPtr += 2; - if (READ_LE_UINT32(_avoDataPtr) != 0) { - _avoDataPtr += 4; - tmpState->sndItem = loadFromAvo_LE_UINT16(); - } else { - _avoDataPtr += 6; - tmpState->sndItem = -1; - } - tmpState->freq = loadFromAvo_LE_UINT16(); - tmpState->repCount = loadFromAvo_LE_UINT16(); - tmpState->sndFrame = loadFromAvo_LE_UINT16(); - } - } - delete[] tempstatedata; - } - - _vm->_goblin->_objects[10] = new Goblin::Gob_Object; - memset(_vm->_goblin->_objects[10], 0, sizeof(Goblin::Gob_Object)); - - _vm->_goblin->_objects[10]->stateMach = new Goblin::Gob_StateLine[40]; - for (state = 0; state < 40; ++state) - for (col = 0; col < 6; ++col) - _vm->_goblin->_objects[10]->stateMach[state][col] = 0; - - pState = new Goblin::Gob_State; - _vm->_goblin->_objects[10]->stateMach[0][0] = pState; - - memset(pState, 0, sizeof(Goblin::Gob_State)); - pState->animation = 9; - pState->layer = 27; - pState->unk0 = 0; - pState->unk1 = 0; - pState->sndItem = -1; - pState->sndFrame = 0; - - _vm->_goblin->placeObject(_vm->_goblin->_objects[10], 1); - - _vm->_goblin->_objects[10]->realStateMach = _vm->_goblin->_objects[10]->stateMach; - _vm->_goblin->_objects[10]->type = 1; - _vm->_goblin->_objects[10]->unk14 = 1; - - state = loadFromAvo_LE_UINT16(); - for (i = 0; i < state; i++) { - _avoDataPtr += 30; - - loadDataFromAvo((char *)&flag, 4); - _avoDataPtr += 56; - - if (flag != 0) - _avoDataPtr += 30; - } - - loadDataFromAvo((char *)&tmp, 2); - _avoDataPtr += 48; - loadItemToObject(); - _avoDataPtr = savedPtr; - - for (i = 0; i < soundCount; i++) { - loadDataFromAvo(buf, 14); - strcat(buf, ".SND"); - strcpy(sndNames[i], buf); - } - - delete[] dataBuf; - - _vm->_goblin->_soundData[14] = _vm->_snd->loadSoundData("diamant1.snd"); - - for (i = 0; i < soundCount; i++) { - handle = _vm->_dataio->openData(sndNames[i]); - if (handle < 0) - continue; - - _vm->_dataio->closeData(handle); - _vm->_goblin->_soundData[i] = _vm->_snd->loadSoundData(sndNames[i]); - } -} - void Map::loadMapsInitGobs(void) { int16 layer; int16 i; diff --git a/engines/gob/map.h b/engines/gob/map.h index 59e9a3bdf9..1b12f9280f 100644 --- a/engines/gob/map.h +++ b/engines/gob/map.h @@ -85,11 +85,13 @@ public: int16 checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 i1); void optimizePoints(void); void loadItemToObject(void); - void loadMapObjects(char *avjFile); void loadDataFromAvo(char *dest, int16 size); void loadMapsInitGobs(void); + virtual void loadMapObjects(char *avjFile) = 0; + Map(GobEngine *vm); + virtual ~Map() {}; protected: char *_avoDataPtr; @@ -99,6 +101,22 @@ protected: uint16 loadFromAvo_LE_UINT16(); }; +class Map_v1 : public Map { +public: + virtual void loadMapObjects(char *avjFile); + + Map_v1(GobEngine *vm); + virtual ~Map_v1() {}; +}; + +class Map_v2 : public Map_v1 { +public: + virtual void loadMapObjects(char *avjFile); + + Map_v2(GobEngine *vm); + virtual ~Map_v2() {}; +}; + } // End of namespace Gob #endif /* __MAP_H */ diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp new file mode 100644 index 0000000000..4e9859b89f --- /dev/null +++ b/engines/gob/map_v1.cpp @@ -0,0 +1,346 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 Ivan Dubrov + * Copyright (C) 2004-2006 The ScummVM project + * + * 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/map.h" +#include "gob/dataio.h" +#include "gob/goblin.h" +#include "gob/sound.h" + +namespace Gob { + +Map_v1::Map_v1(GobEngine *vm) : Map(vm) { +} + +void Map_v1::loadMapObjects(char *avjFile) { + int16 i; + char avoName[128]; + int16 handle; + char item; + int16 soundCount; + int16 tmp; + char *savedPtr; + char *savedPtr2; + char *savedPtr3; + int16 state; + int16 col; + int32 flag; + Goblin::Gob_State *pState; + char buf[128]; + char sndNames[20][14]; + char *dataBuf; + int16 x; + int16 y; + int16 count2; + int16 count3; + + strcpy(avoName, _sourceFile); + strcat(avoName, ".avo"); + + handle = _vm->_dataio->openData(avoName); + if (handle >= 0) { + _loadFromAvo = 1; + _vm->_dataio->closeData(handle); + _avoDataPtr = _vm->_dataio->getData(avoName); + dataBuf = _avoDataPtr; + loadDataFromAvo((char *)_passMap, kMapHeight * kMapWidth); + + for (y = 0; y < kMapHeight; y++) { + for (x = 0; x < kMapWidth; x++) { + loadDataFromAvo(&item, 1); + _itemsMap[y][x] = item; + } + } + + for (i = 0; i < 40; i++) { + _wayPoints[i].x = loadFromAvo_LE_UINT16(); + _wayPoints[i].y = loadFromAvo_LE_UINT16(); + } + loadDataFromAvo((char *)_itemPoses, szMap_ItemPos * 20); + } else { + _loadFromAvo = 0; + _avoDataPtr = _vm->_dataio->getData(avjFile); + dataBuf = _avoDataPtr; + } + + _avoDataPtr += 32; + _avoDataPtr += 76; + _avoDataPtr += 4; + _avoDataPtr += 20; + + for (i = 0; i < 3; i++) { + tmp = loadFromAvo_LE_UINT16(); + _avoDataPtr += tmp * 14; + } + + soundCount = loadFromAvo_LE_UINT16(); + savedPtr = _avoDataPtr; + + _avoDataPtr += 14 * soundCount; + _avoDataPtr += 4; + _avoDataPtr += 24; + + count2 = loadFromAvo_LE_UINT16(); + count3 = loadFromAvo_LE_UINT16(); + + savedPtr2 = _avoDataPtr; + _avoDataPtr += count2 * 8; + + savedPtr3 = _avoDataPtr; + _avoDataPtr += count3 * 8; + + _vm->_goblin->_gobsCount = loadFromAvo_LE_UINT16(); + for (i = 0; i < _vm->_goblin->_gobsCount; i++) { + _vm->_goblin->_goblins[i] = new Goblin::Gob_Object; + + _vm->_goblin->_goblins[i]->xPos = READ_LE_UINT16(savedPtr2); + savedPtr2 += 2; + + _vm->_goblin->_goblins[i]->yPos = READ_LE_UINT16(savedPtr2); + savedPtr2 += 2; + + _vm->_goblin->_goblins[i]->order = READ_LE_UINT16(savedPtr2); + savedPtr2 += 2; + + _vm->_goblin->_goblins[i]->state = READ_LE_UINT16(savedPtr2); + savedPtr2 += 2; + + if (i == 3) + _vm->_goblin->_goblins[i]->stateMach = new Goblin::Gob_StateLine[70]; + else + _vm->_goblin->_goblins[i]->stateMach = new Goblin::Gob_StateLine[40]; + + uint32* tempstatedata = new uint32[40*6]; + for (state = 0; state < 40; ++state) { + for (col = 0; col < 6; ++col) { + tempstatedata[state*6+col] = READ_LE_UINT32(_avoDataPtr); + _avoDataPtr += 4; + } + } + _avoDataPtr += 160; + _vm->_goblin->_goblins[i]->multObjIndex = *_avoDataPtr; + _avoDataPtr += 2; + + _vm->_goblin->_goblins[i]->realStateMach = _vm->_goblin->_goblins[i]->stateMach; + for (state = 0; state < 40; state++) { + for (col = 0; col < 6; col++) { + if (tempstatedata[state*6+col] == 0) { + _vm->_goblin->_goblins[i]->stateMach[state][col] = 0; + continue; + } + + Goblin::Gob_State *tmpState = new Goblin::Gob_State; + _vm->_goblin->_goblins[i]->stateMach[state][col] = tmpState; + + tmpState->animation = loadFromAvo_LE_UINT16(); + tmpState->layer = loadFromAvo_LE_UINT16(); + _avoDataPtr += 8; + tmpState->unk0 = loadFromAvo_LE_UINT16(); + tmpState->unk1 = loadFromAvo_LE_UINT16(); + + _avoDataPtr += 2; + if (READ_LE_UINT32(_avoDataPtr) != 0) { + _avoDataPtr += 4; + tmpState->sndItem = loadFromAvo_LE_UINT16(); + } else { + _avoDataPtr += 6; + tmpState->sndItem = -1; + } + tmpState->freq = loadFromAvo_LE_UINT16(); + tmpState->repCount = loadFromAvo_LE_UINT16(); + tmpState->sndFrame = loadFromAvo_LE_UINT16(); + } + } + delete[] tempstatedata; + } + + pState = new Goblin::Gob_State; + _vm->_goblin->_goblins[0]->stateMach[39][0] = pState; + pState->animation = 0; + pState->layer = 98; + pState->unk0 = 0; + pState->unk1 = 0; + pState->sndItem = -1; + + pState = new Goblin::Gob_State; + _vm->_goblin->_goblins[1]->stateMach[39][0] = pState; + pState->animation = 0; + pState->layer = 99; + pState->unk0 = 0; + pState->unk1 = 0; + pState->sndItem = -1; + + pState = new Goblin::Gob_State; + _vm->_goblin->_goblins[2]->stateMach[39][0] = pState; + pState->animation = 0; + pState->layer = 100; + pState->unk0 = 0; + pState->unk1 = 0; + pState->sndItem = -1; + + _vm->_goblin->_goblins[2]->stateMach[10][0]->sndFrame = 13; + _vm->_goblin->_goblins[2]->stateMach[11][0]->sndFrame = 13; + _vm->_goblin->_goblins[2]->stateMach[28][0]->sndFrame = 13; + _vm->_goblin->_goblins[2]->stateMach[29][0]->sndFrame = 13; + + _vm->_goblin->_goblins[1]->stateMach[10][0]->sndFrame = 13; + _vm->_goblin->_goblins[1]->stateMach[11][0]->sndFrame = 13; + + for (state = 40; state < 70; state++) { + pState = new Goblin::Gob_State; + _vm->_goblin->_goblins[3]->stateMach[state][0] = pState; + _vm->_goblin->_goblins[3]->stateMach[state][1] = 0; + + pState->animation = 9; + pState->layer = state - 40; + pState->sndItem = -1; + pState->sndFrame = 0; + } + + _vm->_goblin->_objCount = loadFromAvo_LE_UINT16(); + for (i = 0; i < _vm->_goblin->_objCount; i++) { + _vm->_goblin->_objects[i] = new Goblin::Gob_Object; + + _vm->_goblin->_objects[i]->xPos = READ_LE_UINT16(savedPtr3); + savedPtr3 += 2; + + _vm->_goblin->_objects[i]->yPos = READ_LE_UINT16(savedPtr3); + savedPtr3 += 2; + + _vm->_goblin->_objects[i]->order = READ_LE_UINT16(savedPtr3); + savedPtr3 += 2; + + _vm->_goblin->_objects[i]->state = READ_LE_UINT16(savedPtr3); + savedPtr3 += 2; + + _vm->_goblin->_objects[i]->stateMach = new Goblin::Gob_StateLine[40]; + + uint32* tempstatedata = new uint32[40*6]; + for (state = 0; state < 40; ++state) { + for (col = 0; col < 6; ++col) { + tempstatedata[state*6+col] = READ_LE_UINT32(_avoDataPtr); + _avoDataPtr += 4; + } + } + _avoDataPtr += 160; + _vm->_goblin->_objects[i]->multObjIndex = *_avoDataPtr; + _avoDataPtr += 2; + + _vm->_goblin->_objects[i]->realStateMach = _vm->_goblin->_objects[i]->stateMach; + for (state = 0; state < 40; state++) { + for (col = 0; col < 6; col++) { + if (tempstatedata[state*6+col] == 0) { + _vm->_goblin->_objects[i]->stateMach[state][col] = 0; + continue; + } + + Goblin::Gob_State *tmpState = new Goblin::Gob_State; + _vm->_goblin->_objects[i]->stateMach[state][col] = tmpState; + + tmpState->animation = loadFromAvo_LE_UINT16(); + tmpState->layer = loadFromAvo_LE_UINT16(); + _avoDataPtr += 8; + tmpState->unk0 = loadFromAvo_LE_UINT16(); + tmpState->unk1 = loadFromAvo_LE_UINT16(); + + _avoDataPtr += 2; + if (READ_LE_UINT32(_avoDataPtr) != 0) { + _avoDataPtr += 4; + tmpState->sndItem = loadFromAvo_LE_UINT16(); + } else { + _avoDataPtr += 6; + tmpState->sndItem = -1; + } + tmpState->freq = loadFromAvo_LE_UINT16(); + tmpState->repCount = loadFromAvo_LE_UINT16(); + tmpState->sndFrame = loadFromAvo_LE_UINT16(); + } + } + delete[] tempstatedata; + } + + _vm->_goblin->_objects[10] = new Goblin::Gob_Object; + memset(_vm->_goblin->_objects[10], 0, sizeof(Goblin::Gob_Object)); + + _vm->_goblin->_objects[10]->stateMach = new Goblin::Gob_StateLine[40]; + for (state = 0; state < 40; ++state) + for (col = 0; col < 6; ++col) + _vm->_goblin->_objects[10]->stateMach[state][col] = 0; + + pState = new Goblin::Gob_State; + _vm->_goblin->_objects[10]->stateMach[0][0] = pState; + + memset(pState, 0, sizeof(Goblin::Gob_State)); + pState->animation = 9; + pState->layer = 27; + pState->unk0 = 0; + pState->unk1 = 0; + pState->sndItem = -1; + pState->sndFrame = 0; + + _vm->_goblin->placeObject(_vm->_goblin->_objects[10], 1, 0, 0, 0, 0); + + _vm->_goblin->_objects[10]->realStateMach = _vm->_goblin->_objects[10]->stateMach; + _vm->_goblin->_objects[10]->type = 1; + _vm->_goblin->_objects[10]->unk14 = 1; + + state = loadFromAvo_LE_UINT16(); + for (i = 0; i < state; i++) { + _avoDataPtr += 30; + + loadDataFromAvo((char *)&flag, 4); + _avoDataPtr += 56; + + if (flag != 0) + _avoDataPtr += 30; + } + + loadDataFromAvo((char *)&tmp, 2); + _avoDataPtr += 48; + loadItemToObject(); + _avoDataPtr = savedPtr; + + for (i = 0; i < soundCount; i++) { + loadDataFromAvo(buf, 14); + strcat(buf, ".SND"); + strcpy(sndNames[i], buf); + } + + delete[] dataBuf; + + _vm->_goblin->_soundData[14] = _vm->_snd->loadSoundData("diamant1.snd"); + + for (i = 0; i < soundCount; i++) { + handle = _vm->_dataio->openData(sndNames[i]); + if (handle < 0) + continue; + + _vm->_dataio->closeData(handle); + _vm->_goblin->_soundData[i] = _vm->_snd->loadSoundData(sndNames[i]); + } +} + +} // End of namespace Gob diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp new file mode 100644 index 0000000000..d8ef031cc9 --- /dev/null +++ b/engines/gob/map_v2.cpp @@ -0,0 +1,192 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 Ivan Dubrov + * Copyright (C) 2004-2006 The ScummVM project + * + * 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/map.h" +#include "gob/dataio.h" +#include "gob/goblin.h" +#include "gob/sound.h" +#include "gob/inter.h" +#include "gob/game.h" +#include "gob/parse.h" +#include "gob/mult.h" + +namespace Gob { + +Map_v2::Map_v2(GobEngine *vm) : Map_v1(vm) { +} + +void Map_v2::loadMapObjects(char *avjFile) { + int i; + int j; + int k; + int16 var; + int16 id; + int16 numChunks; + int16 chunkLength; + int16 offVar; + int16 offData; + int16 tmp; + int16 numData; + int16 statesCount; + int16 state; + char *variables; + char *extData; + char *dataPtr; + char *dataPtrBak; + char *dataPtrBak2; + char statesMask[102]; + Goblin::Gob2_State *statesPtr; + + uint8 var_9; + uint8 byte_2F2AA; + byte *off_2F2AB; + + var = _vm->_parse->parseVarIndex(); + variables = _vm->_global->_inter_variables + var; + + id = _vm->_inter->load16(); + + if (id == -1) { + _vm->_goblin->_dword_2F2A4 = _vm->_global->_inter_variables + var; + return; + } + + extData = _vm->_game->loadExtData(id, 0, 0); + dataPtr = extData; + + if (*dataPtr++ == 3) { + _vm->_mult->_word_2F22A = 640; + _vm->_mult->_word_2CC84 = 65; + } else { + _vm->_mult->_word_2F22A = 320; + _vm->_mult->_word_2CC84 = 40; + } + byte_2F2AA = *dataPtr++; + _vm->_mult->_word_2F2B1 = READ_LE_UINT16(dataPtr); + dataPtr += 2; + _vm->_mult->_word_2F2AF = READ_LE_UINT16(dataPtr); + dataPtr += 2; + + _vm->_mult->_word_2CC86 = _vm->_mult->_word_2F2AF & 0xFF00 ? 0 : 1; + _vm->_mult->_word_2F2AF &= 0xFF; + + dataPtrBak = dataPtr; + dataPtr += (_vm->_mult->_word_2F22A / _vm->_mult->_word_2F2B1) * (200 / _vm->_mult->_word_2F2AF); + + if (*extData == 1) { + byte_2F2AA = 40; + var_9 = 40; + } else { + if (byte_2F2AA == 0) { + var_9 = 1; + } else { + var_9 = byte_2F2AA; + } + } + + off_2F2AB = new byte[3 * var_9]; + memset(off_2F2AB, -1, 3 * var_9); + memcpy(off_2F2AB, dataPtr, 3 * byte_2F2AA); + dataPtr += 3 * byte_2F2AA; + + // In the original asm, this writes byte-wise into the variables-array + if (variables != _vm->_global->_inter_variables) { + _vm->_goblin->_dword_2F2A4 = variables; + numChunks = 200 / _vm->_mult->_word_2F2AF; + chunkLength = _vm->_mult->_word_2F22A / _vm->_mult->_word_2F2B1; + for (i = 0; i < numChunks; i++) { + offVar = _vm->_mult->_word_2CC84 * i; + offData = (chunkLength * i); + for (j = 0; j < chunkLength; j++) { + _vm->_util->writeVariableByte(_vm->_goblin->_dword_2F2A4 + offVar + j, + *(dataPtrBak + offData + j)); + } + } + } + + tmp = READ_LE_UINT16(dataPtr); + dataPtr += tmp * 14 + 2; + tmp = READ_LE_UINT16(dataPtr); + dataPtr += tmp * 14 + 2; + dataPtr += 28; + tmp = READ_LE_UINT16(dataPtr); + dataPtr += tmp * 14 + 2; + + _vm->_goblin->_gobsCount = tmp; + for (i = 0; i < _vm->_goblin->_gobsCount; i++) { + memset(statesMask, -1, 101); + _vm->_mult->_objects[i].goblinStates = new Goblin::Gob2_State*[101]; + memset(_vm->_mult->_objects[i].goblinStates, 0, 101 * sizeof(Goblin::Gob2_State *)); + memcpy(statesMask, dataPtr, 100); + dataPtr += 100; + dataPtrBak2 = dataPtr; + statesCount = 0; + for (j = 0; j < 100; j++) { + if (statesMask[j] != -1) { + statesCount++; + dataPtr += 4; + numData = *dataPtr++; + statesCount += numData; + dataPtr += numData * 9; + } + } + statesPtr = new Goblin::Gob2_State[statesCount]; + _vm->_mult->_objects[i].goblinStates[0] = statesPtr; + dataPtr = dataPtrBak2; + for (j = 0; j < 100; j++) { + state = statesMask[j]; + if (state != -1) { + _vm->_mult->_objects[i].goblinStates[state] = statesPtr++; + _vm->_mult->_objects[i].goblinStates[state][0].animation = READ_LE_UINT16(dataPtr); + dataPtr += 2; + _vm->_mult->_objects[i].goblinStates[state][0].layer = READ_LE_UINT16(dataPtr); + dataPtr += 2; + numData = *dataPtr++; + _vm->_mult->_objects[i].goblinStates[state][0].field_4 = numData; + for (k = 0; k < numData; k++) { + dataPtr++; + _vm->_mult->_objects[i].goblinStates[state][k].animation = *dataPtr << 8; + dataPtr += 2; + _vm->_mult->_objects[i].goblinStates[state][k].animation += *dataPtr; + dataPtr += 2; + _vm->_mult->_objects[i].goblinStates[state][k].layer = *dataPtr << 8; + dataPtr += 2; + _vm->_mult->_objects[i].goblinStates[state][k].layer += *dataPtr; + _vm->_mult->_objects[i].goblinStates[state][k].field_4 = READ_LE_UINT16(dataPtr); + dataPtr += 2; + statesPtr++; + } + } + } + } + + _vm->_goblin->_soundSlotsCount = _vm->_inter->load16(); + for (i = 0; i < _vm->_goblin->_soundSlotsCount; i++) + _vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1); +} + +} // End of namespace Gob diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 5a19baa6f8..9a8ba2c0ea 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -14,6 +14,8 @@ MODULE_OBJS := \ global.o \ gob.o \ goblin.o \ + goblin_v1.o \ + goblin_v2.o \ init.o \ init_v1.o \ init_v2.o \ @@ -21,6 +23,8 @@ MODULE_OBJS := \ inter_v1.o \ inter_v2.o \ map.o \ + map_v1.o \ + map_v2.o \ mult.o \ mult_v1.o \ mult_v2.o \ diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 0ad2fb5b50..3960cb2b6a 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -120,8 +120,12 @@ Mult::Mult(GobEngine *vm) : _vm(vm) { } _orderArray = 0; - warning("GOB2 Stub! _word_2CC88"); - _word_2CC88 = -1; + warning("GOB2 Stub! _word_2F2B1, _word_2F2AF, _word_2CC86, _word_2F22A, _word_2CC84"); + _word_2F2B1 = 0; + _word_2F2AF = 0; + _word_2CC86 = 0; + _word_2F22A = 0; + _word_2CC84 = 0; } void Mult::interGetObjAnimSize(void) { diff --git a/engines/gob/mult.h b/engines/gob/mult.h index 65b3a02238..d09260fa25 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -25,6 +25,7 @@ #include "gob/sound.h" #include "gob/video.h" +#include "gob/goblin.h" namespace Gob { @@ -49,7 +50,15 @@ public: int8 somethingLayer; // New in GOB2 int8 somethingFrame; // New in GOB2 int8 someFlag; // New in GOB2 + int8 state; // New in GOB2 + int8 field_E; // New in GOB2 int8 field_F; // New in GOB2 + int8 field_10; // New in GOB2 + int8 field_12; // New in GOB2 + int8 field_13; // New in GOB2 + int8 field_14; // New in GOB2 + int8 field_15; // New in GOB2 + int8 field_17; // New in GOB2 } GCC_PACK; struct Mult_Object { @@ -61,11 +70,18 @@ public: int16 lastRight; int16 lastTop; int16 lastBottom; - int8 someFlag; // New in GOB2 - int16 somethingLeft; // New in GOB2 - int16 somethingTop; // New in GOB2 - int16 somethingRight; // New in GOB2 - int16 somethingBottom; // New in GOB2 + int8 someFlag; // New in GOB2 + int16 somethingLeft; // New in GOB2 + int16 somethingTop; // New in GOB2 + int16 somethingRight; // New in GOB2 + int16 somethingBottom; // New in GOB2 + int8 goblinX; // New in GOB2 + int8 goblinY; // New in GOB2 + int8 field_1C; // New in GOB2 + int8 field_1D; // New in GOB2 + int8 field_1E; // New in GOB2 + int8 field_1F; // New in GOB2 + Goblin::Gob2_State **goblinStates; // New in GOB2 }; struct Mult_StaticKey { @@ -186,7 +202,11 @@ public: int8 *_orderArray; - int16 _word_2CC88; + uint16 _word_2F2B1; + uint16 _word_2F2AF; + uint16 _word_2CC86; + uint16 _word_2F22A; + uint16 _word_2CC84; void zeroMultData(void); void checkFreeMult(void); @@ -218,7 +238,7 @@ protected: virtual char prepPalAnim(char stop) = 0; virtual void doPalAnim(void) = 0; virtual char doFadeAnim(char stop) = 0; - virtual char doSoundAnim(char stop) = 0; + virtual char doSoundAnim(char stop, int16 frame) = 0; }; class Mult_v1 : public Mult { @@ -243,7 +263,7 @@ protected: virtual char prepPalAnim(char stop); virtual void doPalAnim(void); virtual char doFadeAnim(char stop); - virtual char doSoundAnim(char stop); + virtual char doSoundAnim(char stop, int16 frame); }; class Mult_v2 : public Mult_v1 { @@ -325,7 +345,7 @@ protected: virtual char prepPalAnim(char stop); virtual void doPalAnim(void); virtual char doFadeAnim(char stop); - virtual char doSoundAnim(char stop); + virtual char doSoundAnim(char stop, int16 frame); void sub_62DD(int16 index); void sub_6A35(void); diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index 37ede23366..f0dc7410ef 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -305,7 +305,7 @@ void Mult_v1::playMult(int16 startFrame, int16 endFrame, char checkEscape, doPalAnim(); stop = doFadeAnim(stop); - stop = doSoundAnim(stop); + stop = doSoundAnim(stop, _frame); if (_frame >= endFrame) stopNoClear = 1; @@ -597,11 +597,11 @@ char Mult_v1::doFadeAnim(char stop) { return stop; } -char Mult_v1::doSoundAnim(char stop) { +char Mult_v1::doSoundAnim(char stop, int16 frame) { Mult_SndKey *sndKey; for (_index = 0; _index < _sndKeysCount; _index++) { sndKey = &_sndKeys[_index]; - if (sndKey->frame != _frame) + if (sndKey->frame != frame) continue; if (sndKey->cmd != -1) { diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 09ddef4b43..032f1702eb 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -34,6 +34,7 @@ #include "gob/draw.h" #include "gob/palanim.h" #include "gob/parse.h" +#include "gob/music.h" namespace Gob { @@ -56,6 +57,17 @@ void Mult_v2::loadMult(int16 resId) { index = (resId & 0x8000) ? *_vm->_global->_inter_execPtr++ : 0; _multData2 = new Mult_Data; + + // ---. + for (i = 0; i < 4; i++) { + _multData2->field_157[i] = 0; + for (j = 0; j < 4; j++) { + _multData2->field_15F[i][j] = 0; + _multData2->field_17F[i][j] = 0; + } + } + // ---' + _multDatas[index] = _multData2; for (i = 0; i < 10; i++) { @@ -361,6 +373,7 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape, _objCount = 4; _objects = new Mult_Object[_objCount]; + _orderArray = new int8[_objCount]; _renderData = new int16[9 * _objCount]; _renderData2 = new Mult_Object*[_objCount]; @@ -369,6 +382,14 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape, _animArrayY = new int32[_objCount]; _animArrayData = new Mult_AnimData[_objCount]; + // TODO: Delete that after the code that initializes these fields exists! + int i; + for (i = 0; i < _objCount; i++) { + _animArrayData[i].field_13 = 0; + _animArrayData[i].field_14 = 0; + _animArrayData[i].field_17 = 0; + } + // ---' for (_counter = 0; _counter < _objCount; _counter++) { multObj = &_objects[_counter]; @@ -427,6 +448,7 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape, } do { + _vm->_snd->loopSounds(); stop = 1; if (VAR(58) == 0) { @@ -449,7 +471,7 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape, doPalAnim(); stop = doFadeAnim(stop); - stop = doSoundAnim(stop); + stop = doSoundAnim(stop, _frame); if (_frame >= endFrame) stopNoClear = 1; @@ -771,23 +793,18 @@ char Mult_v2::doFadeAnim(char stop) { return stop; } -char Mult_v2::doSoundAnim(char stop) { +char Mult_v2::doSoundAnim(char stop, int16 frame) { Mult_SndKey *sndKey; for (_index = 0; _index < _multData2->sndKeysCount; _index++) { sndKey = &_multData2->sndKeys[_index]; - if (sndKey->frame != _frame) + if (sndKey->frame != frame) continue; if (sndKey->cmd != -1) { - if (sndKey->cmd == 1) { - _vm->_snd->stopSound(0); - stop = 0; - playSound(_vm->_game->_soundSamples[sndKey->soundIndex], sndKey->repCount, - sndKey->freq, sndKey->channel); - - } else if (sndKey->cmd == 4) { + if ((sndKey->cmd == 1) || (sndKey->cmd == 4)) { _vm->_snd->stopSound(0); - stop = 0; + if (_vm->_game->_soundSamples[sndKey->soundIndex] == 0) + continue; playSound(_vm->_game->_soundSamples[sndKey->soundIndex], sndKey->repCount, sndKey->freq, sndKey->channel); } @@ -817,6 +834,8 @@ void Mult_v2::sub_62DD(int16 index) { for (i = 0; i < 4; i++) { if (_multData2->field_124[index][i] != -1) { for (j = _multData2->field_15F[index][i]; j < _multData2->animKeysCount[i]; j++) { + if ((i >= 4) || (j >= _multData2->animKeysCount[i])) + continue; animKey = &_multData2->animKeys[i][j]; if (animKey->frame > frame) break; @@ -894,6 +913,43 @@ void Mult_v2::sub_62DD(int16 index) { warning("GOB2 Stub! sub_1CBF8(arg0, arg1, arg2, arg3);"); } } + + doSoundAnim(0, frame); + + if (_multData2->field_156 == 1) { // loc_6809 + frame++; + if (_multData2->field_157[index] == (frame-1)) { + _multData2->somepointer05indices[0] = -1; + _multData2->somepointer05indices[1] = -1; + _multData2->somepointer05indices[2] = -1; + _multData2->somepointer05indices[3] = -1; + frame = -1; + for (i = 0; i < 4; i++) { + if ((_multData2->field_124[index][i] == -1) || (_multData2->field_124[index][i] == 1024)) + continue; + _objects[_multData2->field_124[index][i]].pAnimData->animType = + _objects[_multData2->field_124[index][i]].pAnimData->field_17; + } + } + } else { // loc_68F3 + frame--; + if (_multData2->field_157[index] == (frame+1)) { + _multData2->somepointer05indices[0] = -1; + _multData2->somepointer05indices[1] = -1; + _multData2->somepointer05indices[2] = -1; + _multData2->somepointer05indices[3] = -1; + frame = -1; + for (i = 0; i < 4; i++) { + if ((_multData2->field_124[index][i] == -1) || (_multData2->field_124[index][i] == 1024)) + continue; + _objects[_multData2->field_124[index][i]].pAnimData->animType = + _objects[_multData2->field_124[index][i]].pAnimData->field_17; + } + } + } + // loc_6A06 + _multData2->animKeysIndices1[index] = frame; + WRITE_VAR(18 + index, frame); } void Mult_v2::sub_6A35(void) { @@ -1043,7 +1099,7 @@ void Mult_v2::animate(void) { } } - if (_word_2CC88 >= 0) { + if (_vm->_goblin->_gobsCount >= 0) { for (i = 0; i < orderArrayPos; i++) { animObj1 = _renderData2[orderArray[i]]; for (j = i+1; j < orderArrayPos; j++) { @@ -1135,7 +1191,7 @@ void Mult_v2::animate(void) { if (animData1->maxTick == animObj1->tick) { animObj1->tick = 0; - if ((animData1->animType < 100) || (_word_2CC88 < 0)) { + if ((animData1->animType < 100) || (_vm->_goblin->_gobsCount < 0)) { if (animData1->animType == 4) { animData1->frame = 0; animData1->isPaused = 1; @@ -1217,8 +1273,18 @@ void Mult_v2::animate(void) { void Mult_v2::playSound(Snd::SoundDesc * soundDesc, int16 repCount, int16 freq, int16 channel) { - warning("GOB2 Stub! Mult_v2::playSound()"); -// _vm->_snd->playSample(soundDesc, repCount, freq); + warning("PlaySound(%p, %d, %d, %d), %d", (void *) soundDesc, repCount, freq, channel, soundDesc->frequency); + if (soundDesc->frequency >= 0) { + if (soundDesc->frequency == freq) + _vm->_snd->playSample(soundDesc, repCount, -channel); + else + _vm->_snd->playSample(soundDesc, repCount, freq); + } else { + if (soundDesc->frequency == -freq) + _vm->_snd->playSample(soundDesc, repCount, -channel); + else + _vm->_snd->playSample(soundDesc, repCount, freq); + } } void Mult_v2::freeMultKeys(void) { diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp index a70a6cfe0b..52b37e7206 100644 --- a/engines/gob/music.cpp +++ b/engines/gob/music.cpp @@ -81,7 +81,7 @@ Music::Music(GobEngine *vm) : _vm(vm) { _first = true; _ended = false; _playing = false; - _looping = true; + _repCount = -1; _samplesTillPoll = 0; setFreqs(); @@ -94,21 +94,24 @@ Music::~Music(void) { } void Music::premixerCall(int16 *buf, uint len) { + _mutex.lock(); if (!_playing) { memset(buf, 0, 2 * len * sizeof(int16)); + _mutex.unlock(); return; } else { if (_first) { memset(buf, 0, 2 * len * sizeof(int16)); pollMusic(); + _mutex.unlock(); return; } else { uint32 render; int16 *data = buf; uint datalen = len; - while (datalen) { + while (datalen && _playing) { if (_samplesTillPoll) { render = (datalen > _samplesTillPoll) ? (_samplesTillPoll) : (datalen); datalen -= render; @@ -129,7 +132,11 @@ void Music::premixerCall(int16 *buf, uint len) { _ended = false; _playPos = _data + 3 + (_data[1] + 1) * 0x38; _samplesTillPoll = 0; - if (_looping) { + if (_repCount == -1) { + reset(); + setVoices(); + } else if (_repCount > 0) { + _repCount--; reset(); setVoices(); } @@ -141,6 +148,7 @@ void Music::premixerCall(int16 *buf, uint len) { buf[2 * i] = buf[2 * i + 1] = buf[i]; } } + _mutex.unlock(); } void Music::writeOPL(byte reg, byte val) { @@ -175,6 +183,10 @@ void Music::setFreqs(void) { } void Music::reset() { + OPLResetChip(_opl); + _samplesTillPoll = 0; + + setFreqs(); // Set frequencies and octave to 0; notes off for (int i = 0; i < 9; i++) { writeOPL(0xA0 | i, 0); @@ -299,7 +311,7 @@ void Music::pollMusic(void) { byte volume; uint16 tempo; - if (_playPos > (_data + _dataSize)) { + if ((_playPos > (_data + _dataSize)) && (_dataSize != (uint32) -1)) { _ended = true; return; } @@ -355,7 +367,7 @@ void Music::pollMusic(void) { break; default: warning("Unknown command in ADL, stopping playback"); - _looping = false; + _repCount = 0; _ended = true; break; } @@ -427,6 +439,18 @@ bool Music::loadMusic(const char *filename) { return true; } +void Music::loadFromMemory(byte *data) { + _playing = false; + _repCount = 0; + + _dataSize = (uint32) -1; + _data = data; + + reset(); + setVoices(); + _playPos = _data + 3 + (_data[1] + 1) * 0x38; +} + void Music::unloadMusic(void) { _playing = false; diff --git a/engines/gob/music.h b/engines/gob/music.h index 16aa839cdc..19c7b2d28f 100644 --- a/engines/gob/music.h +++ b/engines/gob/music.h @@ -26,6 +26,7 @@ #include "sound/audiostream.h" #include "sound/fmopl.h" +#include "common/mutex.h" #include "gob/gob.h" @@ -38,14 +39,17 @@ public: Music(GobEngine *vm); ~Music(); + void lock() { _mutex.lock(); } + void unlock() { _mutex.unlock(); } bool playing() { return _playing; } - bool getLooping() { return _looping; } - void setLooping(bool looping) { _looping = looping; } + bool getRepeating(void) { return _repCount; } + void setRepeating (int32 repCount) { _repCount = repCount; } void startPlay(void); - void stopPlay(void) { _playing = false; } + void stopPlay(void) { _mutex.lock(); _playing = false; _mutex.unlock(); } void playTrack(const char *trackname); void playBgMusic(void); bool loadMusic(const char *filename); + void loadFromMemory(byte *data); void unloadMusic(void); // AudioStream API @@ -74,10 +78,11 @@ protected: bool _notOn[11]; byte _pollNotes[16]; uint32 _samplesTillPoll; + int32 _repCount; bool _playing; bool _first; bool _ended; - bool _looping; + Common::Mutex _mutex; GobEngine *_vm; void premixerCall(int16 *buf, uint len); diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp index 9bb0fc2de0..6a7446d63d 100644 --- a/engines/gob/sound.cpp +++ b/engines/gob/sound.cpp @@ -24,6 +24,8 @@ #include "gob/gob.h" #include "gob/global.h" #include "gob/sound.h" +#include "gob/game.h" +#include "gob/util.h" namespace Gob { @@ -93,7 +95,14 @@ void Snd::speakerOff(void) { } void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { - assert(frequency > 0); + if (frequency == 0) + frequency = sndDesc->frequency; + + if (frequency <= 0) { + warning("Attempted to play a sample with a frequency of %d", frequency); + return; + } +// assert(frequency > 0); if (!_vm->_mixer->isSoundHandleActive(sndDesc->handle)) { _vm->_mixer->playRaw(&sndDesc->handle, sndDesc->data, sndDesc->size, frequency, 0); diff --git a/engines/gob/sound.h b/engines/gob/sound.h index d755e9898c..5c989a7a38 100644 --- a/engines/gob/sound.h +++ b/engines/gob/sound.h @@ -45,7 +45,7 @@ public: typedef void (*CleanupFuncPtr) (int16); - SoundDesc *_loopingSounds[5]; // Should be enough + SoundDesc *_loopingSounds[10]; // Should be enough char _playingSound; CleanupFuncPtr _cleanupFunc; diff --git a/engines/gob/util.h b/engines/gob/util.h index 1e707b42c1..17c3c09155 100644 --- a/engines/gob/util.h +++ b/engines/gob/util.h @@ -24,6 +24,7 @@ #define GOB_UTIL_H #include "gob/video.h" +#include "gob/global.h" namespace Gob { @@ -86,6 +87,23 @@ public: static const char trStr1[]; static const char trStr2[]; static const char trStr3[]; + + inline uint8 readVariableByte(char *address) { + int16 whichVar = address - _vm->_global->_inter_variables; + int16 whichVarByte = whichVar % 4; + + whichVar >>= 2; + return ((VAR(whichVar) >> 8 * (3-whichVarByte)) & 0xFF); + } + inline void writeVariableByte(char *address, uint8 value) { + int16 whichVar = address - _vm->_global->_inter_variables; + int16 whichVarByte = whichVar % 4; + + whichVar >>= 2; + VAR(whichVar) &= ~(0xFF << 8 * (3-whichVarByte)); + VAR(whichVar) |= ((uint32) value) << 8 * (3-whichVarByte); + } + Util(GobEngine *vm); protected: diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp index 41680b343b..0dc7055471 100644 --- a/engines/gob/video.cpp +++ b/engines/gob/video.cpp @@ -285,7 +285,7 @@ void Video::drawCircle(Video::SurfaceDesc *dest, int16 x, int16 y, int16 radius, void Video::drawPackedSprite(byte *sprBuf, int16 width, int16 height, int16 x, int16 y, int16 transp, SurfaceDesc *dest) { - if (Video::spriteUncompressor(sprBuf, width, height, x, y, transp, dest)) + if (spriteUncompressor(sprBuf, width, height, x, y, transp, dest)) return; if ((dest->vidMode & 0x7f) != 0x13) @@ -391,135 +391,6 @@ void Video::initPrimary(int16 mode) { } } -char Video::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) { - SurfaceDesc sourceDesc; - byte *memBuffer; - byte *srcPtr; - byte *destPtr; - byte *linePtr; - byte temp; - uint16 sourceLeft; - int16 curWidth; - int16 curHeight; - int16 offset; - int16 counter2; - uint16 cmdVar; - int16 bufPos; - int16 strLen; - - if (!destDesc) - return 1; - - if ((destDesc->vidMode & 0x7f) != 0x13) - error("Video::spriteUncompressor: Video mode 0x%x is not supported!", - destDesc->vidMode & 0x7f); - - if (sprBuf[0] != 1) - return 0; - - if (sprBuf[1] != 2) - return 0; - - if (sprBuf[2] == 2) { - sourceDesc.width = srcWidth; - sourceDesc.height = srcHeight; - sourceDesc.vidMode = 0x93; - sourceDesc.vidPtr = sprBuf + 3; - Video::drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1, - srcHeight - 1, x, y, transp); - return 1; - } else { - memBuffer = new byte[4114]; - if (memBuffer == 0) - return 0; - - srcPtr = sprBuf + 3; - sourceLeft = READ_LE_UINT16(srcPtr); - - destPtr = destDesc->vidPtr + destDesc->width * y + x; - - curWidth = 0; - curHeight = 0; - - linePtr = destPtr; - srcPtr += 4; - - for (offset = 0; offset < 4078; offset++) - memBuffer[offset] = 0x20; - - cmdVar = 0; - bufPos = 4078; - while (1) { - cmdVar >>= 1; - if ((cmdVar & 0x100) == 0) { - cmdVar = *srcPtr | 0xff00; - srcPtr++; - } - if ((cmdVar & 1) != 0) { - temp = *srcPtr++; - if (temp != 0 || transp == 0) - *destPtr = temp; - destPtr++; - curWidth++; - if (curWidth >= srcWidth) { - curWidth = 0; - linePtr += destDesc->width; - destPtr = linePtr; - curHeight++; - if (curHeight >= srcHeight) - break; - } - sourceLeft--; - if (sourceLeft == 0) - break; - - memBuffer[bufPos] = temp; - bufPos++; - bufPos %= 4096; - } else { - offset = *srcPtr; - srcPtr++; - offset |= (*srcPtr & 0xf0) << 4; - strLen = (*srcPtr & 0x0f) + 3; - srcPtr++; - - for (counter2 = 0; counter2 < strLen; - counter2++) { - temp = - memBuffer[(offset + - counter2) % 4096]; - if (temp != 0 || transp == 0) - *destPtr = temp; - destPtr++; - - curWidth++; - if (curWidth >= srcWidth) { - curWidth = 0; - linePtr += destDesc->width; - destPtr = linePtr; - curHeight++; - if (curHeight >= srcHeight) { - delete[] memBuffer; - return 1; - } - } - sourceLeft--; - if (sourceLeft == 0) { - delete[] memBuffer; - return 1; - } - memBuffer[bufPos] = temp; - bufPos++; - bufPos %= 4096; - } - } - } - } - delete[] memBuffer; - return 1; -} - void Video::setHandlers() { _vm->_global->_setAllPalette = 1; } } // End of namespace Gob diff --git a/engines/gob/video.h b/engines/gob/video.h index 293643ed55..24c331d875 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -112,8 +112,6 @@ public: void setPalette(PalDesc * palDesc); void setFullPalette(PalDesc * palDesc); void initPrimary(int16 mode); - char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, int16 x, - int16 y, int16 transp, SurfaceDesc * destDesc); void freeDriver(void); void setHandlers(); @@ -121,6 +119,8 @@ public: int16 color1, int16 color2, int16 transp, SurfaceDesc * dest) = 0; virtual SurfaceDesc *initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags) = 0; virtual void waitRetrace(int16) = 0; + virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, + int16 x, int16 y, int16 transp, SurfaceDesc * destDesc) = 0; protected: class VideoDriver *_videoDriver; @@ -135,6 +135,8 @@ public: int16 color1, int16 color2, int16 transp, SurfaceDesc * dest); virtual SurfaceDesc *initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags); virtual void waitRetrace(int16); + virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, + int16 x, int16 y, int16 transp, SurfaceDesc * destDesc); Video_v1(GobEngine *vm); virtual ~Video_v1() {}; @@ -146,6 +148,8 @@ public: int16 color1, int16 color2, int16 transp, SurfaceDesc * dest); virtual SurfaceDesc *initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags); virtual void waitRetrace(int16); + virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, + int16 x, int16 y, int16 transp, SurfaceDesc * destDesc); Video_v2(GobEngine *vm); virtual ~Video_v2() {}; diff --git a/engines/gob/video_v1.cpp b/engines/gob/video_v1.cpp index cafea57d1e..61b565bcc4 100644 --- a/engines/gob/video_v1.cpp +++ b/engines/gob/video_v1.cpp @@ -113,4 +113,133 @@ Video::SurfaceDesc *Video_v1::initSurfDesc(int16 vidMode, int16 width, int16 hei return descPtr; } +char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, + int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) { + SurfaceDesc sourceDesc; + byte *memBuffer; + byte *srcPtr; + byte *destPtr; + byte *linePtr; + byte temp; + uint16 sourceLeft; + int16 curWidth; + int16 curHeight; + int16 offset; + int16 counter2; + uint16 cmdVar; + int16 bufPos; + int16 strLen; + + if (!destDesc) + return 1; + + if ((destDesc->vidMode & 0x7f) != 0x13) + error("Video::spriteUncompressor: Video mode 0x%x is not supported!", + destDesc->vidMode & 0x7f); + + if (sprBuf[0] != 1) + return 0; + + if (sprBuf[1] != 2) + return 0; + + if (sprBuf[2] == 2) { + sourceDesc.width = srcWidth; + sourceDesc.height = srcHeight; + sourceDesc.vidMode = 0x93; + sourceDesc.vidPtr = sprBuf + 3; + Video::drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1, + srcHeight - 1, x, y, transp); + return 1; + } else { + memBuffer = new byte[4114]; + if (memBuffer == 0) + return 0; + + srcPtr = sprBuf + 3; + sourceLeft = READ_LE_UINT16(srcPtr); + + destPtr = destDesc->vidPtr + destDesc->width * y + x; + + curWidth = 0; + curHeight = 0; + + linePtr = destPtr; + srcPtr += 4; + + for (offset = 0; offset < 4078; offset++) + memBuffer[offset] = 0x20; + + cmdVar = 0; + bufPos = 4078; + while (1) { + cmdVar >>= 1; + if ((cmdVar & 0x100) == 0) { + cmdVar = *srcPtr | 0xff00; + srcPtr++; + } + if ((cmdVar & 1) != 0) { + temp = *srcPtr++; + if (temp != 0 || transp == 0) + *destPtr = temp; + destPtr++; + curWidth++; + if (curWidth >= srcWidth) { + curWidth = 0; + linePtr += destDesc->width; + destPtr = linePtr; + curHeight++; + if (curHeight >= srcHeight) + break; + } + sourceLeft--; + if (sourceLeft == 0) + break; + + memBuffer[bufPos] = temp; + bufPos++; + bufPos %= 4096; + } else { + offset = *srcPtr; + srcPtr++; + offset |= (*srcPtr & 0xf0) << 4; + strLen = (*srcPtr & 0x0f) + 3; + srcPtr++; + + for (counter2 = 0; counter2 < strLen; + counter2++) { + temp = + memBuffer[(offset + + counter2) % 4096]; + if (temp != 0 || transp == 0) + *destPtr = temp; + destPtr++; + + curWidth++; + if (curWidth >= srcWidth) { + curWidth = 0; + linePtr += destDesc->width; + destPtr = linePtr; + curHeight++; + if (curHeight >= srcHeight) { + delete[] memBuffer; + return 1; + } + } + sourceLeft--; + if (sourceLeft == 0) { + delete[] memBuffer; + return 1; + } + memBuffer[bufPos] = temp; + bufPos++; + bufPos %= 4096; + } + } + } + } + delete[] memBuffer; + return 1; +} + } // End of namespace Gob diff --git a/engines/gob/video_v2.cpp b/engines/gob/video_v2.cpp index 8e55154dde..cad6937c0b 100644 --- a/engines/gob/video_v2.cpp +++ b/engines/gob/video_v2.cpp @@ -154,4 +154,153 @@ Video::SurfaceDesc *Video_v2::initSurfDesc(int16 vidMode, int16 width, int16 hei return descPtr; } +char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, + int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) { + SurfaceDesc sourceDesc; + byte *memBuffer; + byte *srcPtr; + byte *destPtr; + byte *linePtr; + byte temp; + uint32 sourceLeft; + int16 curWidth; + int16 curHeight; + int16 offset; + int16 counter2; + uint16 cmdVar; + int16 bufPos; + int16 strLen; + + if (!destDesc) + return 1; + + if ((destDesc->vidMode & 0x7f) != 0x13) + error("Video::spriteUncompressor: Video mode 0x%x is not supported!", + destDesc->vidMode & 0x7f); + + if (sprBuf[0] != 1) + return 0; + + if (sprBuf[1] != 2) + return 0; + + if (sprBuf[2] == 2) { + sourceDesc.width = srcWidth; + sourceDesc.height = srcHeight; + sourceDesc.vidMode = 0x93; + sourceDesc.vidPtr = sprBuf + 3; + Video::drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1, + srcHeight - 1, x, y, transp); + return 1; + } else if (sprBuf[2] == 1) { + memBuffer = new byte[4370]; + if (memBuffer == 0) + return 0; + + srcPtr = sprBuf + 3; + sourceLeft = READ_LE_UINT32(srcPtr); + + // TODO: Needed until wide/scrolling surfaces are supported... + if ((x + srcWidth) >= destDesc->width) + x = 0; + if ((y + srcHeight) >= destDesc->height) + y = 0; + + destPtr = destDesc->vidPtr + destDesc->width * y + x; + + curWidth = 0; + curHeight = 0; + + linePtr = destPtr; + srcPtr += 4; + + int16 var_2E = 0; + int16 var_2F; + if ((READ_LE_UINT16(srcPtr + 2) == 0x5678) && (READ_LE_UINT16(srcPtr) != 0x1234)) { + srcPtr += 4; + bufPos = 273; + var_2F = 18; + } else { + var_2F = 100; + bufPos = 4078; + } + if (transp == 0) + var_2E = 300; + else + var_2E = 0; + + cmdVar = 0; + while (1) { + cmdVar >>= 1; + if ((cmdVar & 0x100) == 0) { + cmdVar = *srcPtr | 0xff00; + srcPtr++; + } + if ((cmdVar & 1) != 0) { + temp = *srcPtr++; + if (temp != var_2E) + *destPtr = temp; + destPtr++; + curWidth++; + if (curWidth >= srcWidth) { + curWidth = 0; + linePtr += destDesc->width; + destPtr = linePtr; + curHeight++; + if (curHeight >= srcHeight) + break; + } + sourceLeft--; + memBuffer[bufPos] = temp; + bufPos++; + bufPos %= 4096; + if (sourceLeft == 0) + break; + } else { + offset = *srcPtr++; + offset |= (*srcPtr & 0xf0) << 4; + strLen = (*srcPtr & 0x0f) + 3; + *srcPtr++; + if (strLen == var_2F) + strLen = *srcPtr++ + 18; + + for (counter2 = 0; counter2 < strLen; + counter2++) { + temp = memBuffer[(offset + counter2) % 4096]; + if (temp != var_2E) + *destPtr = temp; + destPtr++; + + curWidth++; + if (curWidth >= srcWidth) { + curWidth = 0; + linePtr += destDesc->width; + destPtr = linePtr; + curHeight++; + if (curHeight >= srcHeight) { + delete[] memBuffer; + return 1; + } + } + memBuffer[bufPos] = temp; + bufPos++; + bufPos %= 4096; + } + // loc_1D4E4 + + if (strLen < (int32) sourceLeft) + sourceLeft--; + else { + delete[] memBuffer; + return 1; + } + } + } + } else + return 0; + + delete[] memBuffer; + return 1; +} + } // End of namespace Gob -- cgit v1.2.3