From 015d68c114dca6bcc9f80403c103fb6c3ad83732 Mon Sep 17 00:00:00 2001 From: Eric Fry Date: Thu, 1 Aug 2019 09:39:19 +1000 Subject: [PATCH] DRAGONS: Added random function. Cleaned up method names --- engines/dragons/cutscene.cpp | 41 ++++++++--------- engines/dragons/cutscene.h | 2 +- engines/dragons/dragons.cpp | 47 +++++++++++--------- engines/dragons/dragons.h | 6 ++- engines/dragons/saveload.cpp | 3 +- engines/dragons/scriptopcodes.cpp | 74 +++++++------------------------ engines/dragons/scriptopcodes.h | 1 + engines/dragons/talk.cpp | 70 +++++++++++++++++++++++++++++ engines/dragons/talk.h | 3 ++ 9 files changed, 147 insertions(+), 100 deletions(-) diff --git a/engines/dragons/cutscene.cpp b/engines/dragons/cutscene.cpp index c1fdcd29ccb..5d24fa28481 100644 --- a/engines/dragons/cutscene.cpp +++ b/engines/dragons/cutscene.cpp @@ -72,15 +72,15 @@ void CutScene::scene1() { closeUpShotOnActor(0xd3, 0, 0x233, 0x17a); //close up on king //playSoundFromTxtIndex(0x4e26); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,4,0,0x4e26,0x2e01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); closeUpShotOnActor(0xd8, 0, 0xfd, 0x60); // cut to flicker //playSoundFromTxtIndex(0x4ea2); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,2,0,0x4ea2,0x701) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); closeUpShotOnActor(0xd3, 0, 0x233, 0x17a); //close up on king //playSoundFromTxtIndex(0x4eec); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,5,0,0x4eec,0x2e01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); wideAngleEveryoneAtTable(); // shot of whole room if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072dec,4,0,0x5000,0x2e01) != 2 && _vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_800830c0,0x1d,0x1c,0x5074,0x501) != 2 && @@ -89,14 +89,14 @@ void CutScene::scene1() { closeUpShotOnActor(0xd7, 0, 0x312, 0x260); //close up on flame //playSoundFromTxtIndex(0x5152); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,2,0,0x5152,0x3e01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); closeUpShotOnActor(0xd8, 0, 0xfd, 0x60); //close up flicker //playSoundFromTxtIndex(0x51fc); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,3,0,0x51fc,0x701) != 2) { _vm->playSound(0x8004); _vm->waitForFrames(0x28); _vm->playSound(0x8003); - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); DAT_80063514 = DAT_80063514 | 0x40; FUN_8003d8e8(0xd6,0,0x37a,0x280); DAT_80072dec = _vm->_actorManager->loadActor(0xd5,0,0x2d6,0xc6,3); //load humans @@ -114,43 +114,43 @@ void CutScene::scene1() { _vm->_scene->_camera.x = 0; //playSoundFromTxtIndex(0x54dc); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072df0,6,2,0x54dc,0x2e01) != 2) { - FUN_8003c108(DAT_80072de8); - FUN_8003c108(DAT_80072dec); - FUN_8003c108(DAT_80072df0); + clearActor(DAT_80072de8); + clearActor(DAT_80072dec); + clearActor(DAT_80072df0); wideAngleEveryoneAtTable(); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072e08,3,2,0x55d4,0xc01) != 2) { closeUpShotOnActor(0xd4, 0, 0x8a, 0); //close up chancellor //playSoundFromTxtIndex(0x562c); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,2,0,0x562c,0xc01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); FUN_8003d8e8(0xd6,0,0x37a,0x280); DAT_80072dec = _vm->_actorManager->loadActor(0xd5,4,0x2d6,0xc6,3); _vm->waitForFramesAllowSkip(4); // call_fade_related_1f(); if (FUN_8003dab8(0x5780,0x14,0,0xc01,1) != 2) { DAT_80063514 = DAT_80063514 | 0x40; - FUN_8003c108(DAT_80072de8); - FUN_8003c108(DAT_80072dec); + clearActor(DAT_80072de8); + clearActor(DAT_80072dec); closeUpShotOnActor(0xd7, 0, 0x312, 0x260); // close up flame //playSoundFromTxtIndex(0x581c); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,3,0,0x581c,0x3e01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); closeUpShotOnActor(0xd4, 0, 0x8a, 0); //close up chancellor //playSoundFromTxtIndex(0x5942); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,4,0,0x5942,0xc01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); closeUpShotOnActor(0xd3, 2, 0x87, 0); // close up king //playSoundFromTxtIndex(0x5aaa); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,7,2,0x5aaa,0x2e01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); FUN_8003d8e8(0xd6,0,0x37a,0x280); DAT_80072dec = _vm->_actorManager->loadActor(0xd5,0,0x2d6,0xc6,3); _vm->waitForFramesAllowSkip(4); // call_fade_related_1f(); //playSoundFromTxtIndex(0x5afc); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072dec,3,0,0x5afc,0x3c01) != 2) { - FUN_8003c108(DAT_80072de8); - FUN_8003c108(DAT_80072dec); + clearActor(DAT_80072de8); + clearActor(DAT_80072dec); DAT_80063514 = DAT_80063514 & 0xffbf; closeUpKnightsAtTable(); // close up of knights at table. _vm->playSound(0x8003); @@ -172,13 +172,13 @@ void CutScene::scene1() { //call_fade_related_1f(); //playSoundFromTxtIndex(0x5ef2); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072dec,4,0,0x5ef2,0x3e01) != 2) { - FUN_8003c108(DAT_80072de8); - FUN_8003c108(DAT_80072dec); + clearActor(DAT_80072de8); + clearActor(DAT_80072dec); closeUpShotOnActor(0xd3, 0, 0x233, 0x17a); // close up of king //playSoundFromTxtIndex(0x6000); if (_vm->_talk->somethingTextAndSpeechAndAnimRelated(DAT_80072de8,8,0,0x6000,0x2e01) != 2) { - FUN_8003c108(DAT_80072de8); + clearActor(DAT_80072de8); closeUpKnightsAtTable(); // close up knights at table //playSoundFromTxtIndex(0x7dcc); DAT_80072df0->updateSequence(0x13); @@ -342,7 +342,8 @@ void CutScene::scene1() { } -void CutScene::FUN_8003c108(Actor *actor) { +//FUN_8003c108 +void CutScene::clearActor(Actor *actor) { // TODO fade_related_calls_with_1f(); //DisableVSyncEvent(); actor->reset_maybe(); diff --git a/engines/dragons/cutscene.h b/engines/dragons/cutscene.h index ed66c39d8cc..dc7ddf364e9 100644 --- a/engines/dragons/cutscene.h +++ b/engines/dragons/cutscene.h @@ -62,7 +62,7 @@ public: private: //Scene 1 related functions - void FUN_8003c108(Actor *actor); + void clearActor(Actor *actor); void closeUpShotOnActor(uint16 resourceId, uint16 sequenceId, int16 x, uint32 param_4); void FUN_8003d8e8(uint16 resourceId,uint16 sequenceId,int16 x,uint32 param_4); void wideAngleEveryoneAtTable(); diff --git a/engines/dragons/dragons.cpp b/engines/dragons/dragons.cpp index 7fd0dfa39d2..ea7d2a5ba31 100644 --- a/engines/dragons/dragons.cpp +++ b/engines/dragons/dragons.cpp @@ -1039,7 +1039,7 @@ void DragonsEngine::works_with_obd_data_1() { uVar4 = uVar4 | uVar5; } if (((uVar4 & 0xffff) == 0) && ((uVar6 & 0xfffd) == 0)) { - FUN_8002931c(); + _talk->flickerRandomDefaultResponse(); } } else { @@ -1145,24 +1145,6 @@ void DragonsEngine::FUN_80038994() { error("FUN_80038994"); //TODO } -void DragonsEngine::FUN_8002931c() { - - DragonINI *flicker = _dragonINIResource->getFlickerRecord(); - if (flicker && flicker->actor) { - flicker->actor->clearFlag(ACTOR_FLAG_10); - if (getCurrentSceneId() != 0x2e || !flicker->actor->_actorResource || flicker->actor->_actorResource->_id != 0x91) { - flicker->actor->setFlag(ACTOR_FLAG_4); - } - } -//TODO -// uVar1 = FUN_80023830(9); -// local_30 = 0x11; -// local_2c = local_280[(uint)DAT_800728b0 * 9 + (uVar1 & 0xffff)]; -// FlickerTalkMaybe(&local_30); - -error("FUN_8002931c"); //TODO -} - void DragonsEngine::reset_screen_maybe() { data_8006a3a0_flag &= ~0x10; //TODO @@ -1221,6 +1203,7 @@ void DragonsEngine::loadScene(uint16 sceneId) { } void DragonsEngine::reset() { + seedRandom(0x1dd); //TODO should we randomise this better? I got this value from a couple of runs in the emulator _nextUpdatetime = 0; _flags = 0; _unkFlags1 = 0; @@ -1237,7 +1220,7 @@ void DragonsEngine::reset() { } memset(unkArray_uint16, 0, sizeof(unkArray_uint16)); - + setSceneUpdateFunction(NULL); } void DragonsEngine::runSceneUpdaterFunction() { @@ -1251,6 +1234,30 @@ void DragonsEngine::setSceneUpdateFunction(void (*newUpdateFunction)()) { _sceneUpdateFunction = newUpdateFunction; } +void DragonsEngine::seedRandom(int32 seed) { + _randomState = seed * -0x2b0e2b0f; +} + +uint32 DragonsEngine::shuffleRandState() +{ + uint32 returnBit; + + returnBit = _randomState & 1; + _randomState = _randomState >> 1 | + (_randomState << 0x1e ^ _randomState ^ _randomState << 0x1d ^ _randomState << 0x1b ^ + _randomState << 0x19) & 0x80000000; + return returnBit; +} + +uint16 DragonsEngine::getRand(uint16 max) { + uint16 rand = 0; + + for (int i = 0; i < 0x10; i++) { + rand = shuffleRandState() | rand << i; + } + return rand % max; +} + void (*DragonsEngine::getSceneUpdateFunction())() { return _sceneUpdateFunction; } diff --git a/engines/dragons/dragons.h b/engines/dragons/dragons.h index 7fd911f4503..0b660e9ad2e 100644 --- a/engines/dragons/dragons.h +++ b/engines/dragons/dragons.h @@ -163,6 +163,8 @@ private: uint16 run_func_ptr_unk_countdown_timer; + uint32 _randomState; + // input bool _leftMouseButtonUp; bool _rightMouseButtonUp; @@ -225,6 +227,7 @@ public: void (*getSceneUpdateFunction())(); bool checkForActionButtonRelease(); + uint16 getRand(uint16 max); private: bool savegame(const char *filename, const char *description); bool loadgame(const char *filename); @@ -246,7 +249,8 @@ private: void walkFlickerToObject(); void FUN_80038994(); - void FUN_8002931c(); + void seedRandom(int32 seed); + uint32 shuffleRandState(); }; DragonsEngine *getEngine(); diff --git a/engines/dragons/saveload.cpp b/engines/dragons/saveload.cpp index 78685d45ba8..456df1fb4fa 100644 --- a/engines/dragons/saveload.cpp +++ b/engines/dragons/saveload.cpp @@ -128,7 +128,8 @@ bool DragonsEngine::loadgame(const char *filename) { // TODO load game state here. _gameState->read(in); uint16 newSceneId = (uint16)in->readByte(); _dragonFLG->loadState(in); - _dragonFLG->set(165, true); //TODO check why this is needed to load save games properly. + //_dragonFLG->set(165, true); //TODO check why this is needed to load save games properly. + _dragonFLG->set(125, false); //TODO check why this is needed to load save games properly. _dragonVAR->reset(); _dragonINIResource->reset(); diff --git a/engines/dragons/scriptopcodes.cpp b/engines/dragons/scriptopcodes.cpp index 9180f40e18a..6cec4b4b618 100644 --- a/engines/dragons/scriptopcodes.cpp +++ b/engines/dragons/scriptopcodes.cpp @@ -115,7 +115,7 @@ void ScriptOpcodes::initOpcodes() { OPCODE(0x16, opUnk16); OPCODE(0x17, opUnk17); OPCODE(0x18, opUnk18); - + OPCODE(0x19, opUnk19); OPCODE(0x1A, opUnk1A); OPCODE(0x1B, opUnk1B); OPCODE(0x1C, opSetActorFlag0x1000); @@ -786,60 +786,7 @@ void ScriptOpcodes::opUnk11FlickerTalk(ScriptOpCall &scriptOpCall) { ARG_UINT32(textIndex) // TODO implement me! - debug("Main actor talk: 0x%04x and text 0x%04x", iniId, textIndex); - - if (textIndex == 0) { - return; - } - Actor *actor = NULL; - if (iniId == 0) { - //TODO playSoundFromTxtIndex(textIndex); - actor = _vm->_dragonINIResource->getFlickerRecord()->actor; - if (!_vm->isFlagSet(ENGINE_FLAG_2000000)) { - if (_vm->getCurrentSceneId() == 0x32) { - _vm->getINI(0x2b1)->actor->updateSequence(2); - } - else { - actor->setFlag(ACTOR_FLAG_2000); - if (actor->_sequenceID2 != -1) { - actor->updateSequence(actor->_sequenceID2 + 0x10); - } - } - } - else { - if (actor->_sequenceID == 5) { - actor->updateSequence(0x10); - } - } - } - // TODO sVar1 = findTextToDtSpeechIndex(textIndex); - uint16 dialog[2048]; - dialog[0] = 0; - _vm->_talk->loadText(textIndex, dialog, 2048); - -// pcVar2 = (char *)0x0; -// if (((unkFlags1 & 1) == 0) && (((engine_flags_maybe & 0x1000) == 0 || (sVar1 == -1)))) { -// pcVar2 = load_string_from_dragon_txt(textIndex,acStack2016); -// } - _vm->_talk->displayDialogAroundINI(iniId, dialog, textIndex); //TODO need to pass dialog here (pcVar2). not NULL - if (iniId == 0) { - if (!_vm->isFlagSet(ENGINE_FLAG_2000000)) { - if (_vm->getCurrentSceneId() != 0x32) { - actor->setFlag(ACTOR_FLAG_4); - actor->clearFlag(ACTOR_FLAG_2000); - _vm->waitForFrames(1); - return; - } - _vm->getINI(0x2b1)->actor->updateSequence(1); - - } - else { - if (actor->_sequenceID != 0x10) { - return; - } - actor->updateSequence(5); - } - } + _vm->_talk->talkFromIni(iniId, textIndex); } void ScriptOpcodes::opUnk12LoadScene(ScriptOpCall &scriptOpCall) { @@ -1007,8 +954,7 @@ void ScriptOpcodes::opCode_UnkA_setsProperty(ScriptOpCall &scriptOpCall) { s2 -= s1; } else { if (fieldB == 3) { - //TODO s2 = sub_80023830(s1); - error("TODO s2 = sub_80023830(s1);"); + s2 = _vm->getRand(s1); } } } @@ -1110,6 +1056,20 @@ void ScriptOpcodes::opUnk18(ScriptOpCall &scriptOpCall) { _vm->_talk->displayDialogAroundPoint(dialog,x,y,fieldA,1,field2); } +void ScriptOpcodes::opUnk19(ScriptOpCall &scriptOpCall) { + ARG_INT16(field0); + ARG_INT16(size); + + if (scriptOpCall._field8 == 3) { + ScriptOpCall newCall; + newCall._code = scriptOpCall._code; + newCall._codeEnd = scriptOpCall._code + size; + _vm->_scriptOpcodes->runScript(newCall); + } + scriptOpCall._code += size; + +} + void ScriptOpcodes::opUnk1A(ScriptOpCall &scriptOpCall) { ARG_SKIP(2); ARG_INT16(index); diff --git a/engines/dragons/scriptopcodes.h b/engines/dragons/scriptopcodes.h index edffa86604e..fd2cbcfecb6 100644 --- a/engines/dragons/scriptopcodes.h +++ b/engines/dragons/scriptopcodes.h @@ -106,6 +106,7 @@ protected: void opUnk16(ScriptOpCall &scriptOpCall); void opUnk17(ScriptOpCall &scriptOpCall); void opUnk18(ScriptOpCall &scriptOpCall); + void opUnk19(ScriptOpCall &scriptOpCall); void opUnk1A(ScriptOpCall &scriptOpCall); void opUnk1B(ScriptOpCall &scriptOpCall); void opSetActorFlag0x1000(ScriptOpCall &scriptOpCall); diff --git a/engines/dragons/talk.cpp b/engines/dragons/talk.cpp index 83e35957159..d23cd018197 100644 --- a/engines/dragons/talk.cpp +++ b/engines/dragons/talk.cpp @@ -334,5 +334,75 @@ uint Talk::somethingTextAndSpeechAndAnimRelated(Actor *actor, int16 sequenceId1, return 1; //TODO this should get return value from displayDialogAroundActor(); } +void Talk::talkFromIni(uint32 iniId, uint32 textIndex) { + debug("Main actor talk: 0x%04x and text 0x%04x", iniId, textIndex); + + if (textIndex == 0) { + return; + } + Actor *actor = NULL; + if (iniId == 0) { + //TODO playSoundFromTxtIndex(textIndex); + actor = _vm->_dragonINIResource->getFlickerRecord()->actor; + if (!_vm->isFlagSet(ENGINE_FLAG_2000000)) { + if (_vm->getCurrentSceneId() == 0x32) { + _vm->getINI(0x2b1)->actor->updateSequence(2); + } + else { + actor->setFlag(ACTOR_FLAG_2000); + if (actor->_sequenceID2 != -1) { + actor->updateSequence(actor->_sequenceID2 + 0x10); + } + } + } + else { + if (actor->_sequenceID == 5) { + actor->updateSequence(0x10); + } + } + } + // TODO sVar1 = findTextToDtSpeechIndex(textIndex); + uint16 dialog[2048]; + dialog[0] = 0; + _vm->_talk->loadText(textIndex, dialog, 2048); + +// pcVar2 = (char *)0x0; +// if (((unkFlags1 & 1) == 0) && (((engine_flags_maybe & 0x1000) == 0 || (sVar1 == -1)))) { +// pcVar2 = load_string_from_dragon_txt(textIndex,acStack2016); +// } + _vm->_talk->displayDialogAroundINI(iniId, dialog, textIndex); //TODO need to pass dialog here (pcVar2). not NULL + if (iniId == 0) { + if (!_vm->isFlagSet(ENGINE_FLAG_2000000)) { + if (_vm->getCurrentSceneId() != 0x32) { + actor->setFlag(ACTOR_FLAG_4); + actor->clearFlag(ACTOR_FLAG_2000); + _vm->waitForFrames(1); + return; + } + _vm->getINI(0x2b1)->actor->updateSequence(1); + + } + else { + if (actor->_sequenceID != 0x10) { + return; + } + actor->updateSequence(5); + } + } +} + +void Talk::flickerRandomDefaultResponse() { + DragonINI *flicker = _vm->_dragonINIResource->getFlickerRecord(); + if (flicker && flicker->actor) { + flicker->actor->clearFlag(ACTOR_FLAG_10); + if (_vm->getCurrentSceneId() != 0x2e || !flicker->actor->_actorResource || flicker->actor->_actorResource->_id != 0x91) { + flicker->actor->setFlag(ACTOR_FLAG_4); + } + } + uint16 rand = _vm->getRand(9); + //TODO defaultResponseTable[_cursor->data_800728b0_cursor_seqID * 9 + rand]; + talkFromIni(0x11, 0x1902); +} + } // End of namespace Dragons \ No newline at end of file diff --git a/engines/dragons/talk.h b/engines/dragons/talk.h index c0115de8069..367b2c2ee83 100644 --- a/engines/dragons/talk.h +++ b/engines/dragons/talk.h @@ -58,6 +58,9 @@ public: void loadText(uint32 textIndex, uint16 *textBuffer, uint16 bufferLength); void printWideText(byte *text); + void talkFromIni(uint32 iniId, uint32 textIndex); + void flickerRandomDefaultResponse(); + uint32 displayDialogAroundINI(uint32 iniId, uint16 *dialogText, uint32 textIndex); void displayDialogAroundPoint(uint16 *dialogText, uint16 x, uint16 y, uint16 param_4, int16 param_5, uint32 textId); void displayDialogAroundActor(Actor *actor, uint16 param_2, uint16 *dialogText, uint32 textIndex);