/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "common/scummsys.h" #include "access/access.h" #include "access/resources.h" #include "access/scripts.h" namespace Access { Scripts::Scripts(AccessEngine *vm) : Manager(vm) { _resource = nullptr; _specialFunction = -1; _data = nullptr; _sequence = 0; _endFlag = false; _returnCode = 0; _scriptCommand = 0; _choice = 0; _choiceStart = 0; _charsOrg = Common::Point(0, 0); _texsOrg = Common::Point(0, 0); setOpcodes(); } Scripts::~Scripts() { freeScriptData(); } void Scripts::setOpcodes() { COMMAND_LIST[0] = &Scripts::cmdObject; COMMAND_LIST[1] = &Scripts::cmdEndObject; COMMAND_LIST[2] = &Scripts::cmdJumpLook; COMMAND_LIST[3] = &Scripts::cmdJumpHelp; COMMAND_LIST[4] = &Scripts::cmdJumpGet; COMMAND_LIST[5] = &Scripts::cmdJumpMove; COMMAND_LIST[6] = &Scripts::cmdJumpUse; COMMAND_LIST[7] = &Scripts::cmdJumpTalk; COMMAND_LIST[8] = &Scripts::cmdNull; COMMAND_LIST[9] = &Scripts::cmdPrint_v1; COMMAND_LIST[10] = &Scripts::cmdRetPos; COMMAND_LIST[11] = &Scripts::cmdAnim; COMMAND_LIST[12] = &Scripts::cmdSetFlag; COMMAND_LIST[13] = &Scripts::cmdCheckFlag; COMMAND_LIST[14] = &Scripts::cmdGoto; COMMAND_LIST[15] = &Scripts::cmdAddScore; COMMAND_LIST[16] = &Scripts::cmdSetInventory; COMMAND_LIST[17] = &Scripts::cmdCheckInventory; COMMAND_LIST[18] = &Scripts::cmdSetTex; COMMAND_LIST[19] = &Scripts::cmdNewRoom; COMMAND_LIST[20] = &Scripts::cmdConverse; COMMAND_LIST[21] = &Scripts::cmdCheckFrame; COMMAND_LIST[22] = &Scripts::cmdCheckAnim; COMMAND_LIST[23] = &Scripts::cmdSnd; COMMAND_LIST[24] = &Scripts::cmdRetNeg; COMMAND_LIST[25] = &Scripts::cmdRetPos; COMMAND_LIST[26] = &Scripts::cmdCheckLoc; COMMAND_LIST[27] = &Scripts::cmdSetAnim; COMMAND_LIST[28] = &Scripts::cmdDispInv_v1; COMMAND_LIST[29] = &Scripts::cmdSetAbout; COMMAND_LIST[30] = &Scripts::cmdSetTimer; COMMAND_LIST[31] = &Scripts::cmdCheckTimer; COMMAND_LIST[32] = &Scripts::cmdSetTravel; COMMAND_LIST[33] = &Scripts::cmdJumpGoto; COMMAND_LIST[34] = &Scripts::cmdSetVideo; COMMAND_LIST[35] = &Scripts::cmdPlayVideo; COMMAND_LIST[36] = &Scripts::cmdPlotImage; COMMAND_LIST[37] = &Scripts::cmdSetDisplay; COMMAND_LIST[38] = &Scripts::cmdSetBuffer; COMMAND_LIST[39] = &Scripts::cmdSetScroll; COMMAND_LIST[40] = &Scripts::cmdSaveRect; COMMAND_LIST[41] = &Scripts::cmdVideoEnded; COMMAND_LIST[42] = &Scripts::cmdSetBufVid; COMMAND_LIST[43] = &Scripts::cmdPlayBufVid; COMMAND_LIST[44] = &Scripts::cmdRemoveLast; COMMAND_LIST[45] = &Scripts::cmdDoTravel; COMMAND_LIST[46] = &Scripts::cmdCheckAbout; COMMAND_LIST[47] = &Scripts::cmdSpecial; COMMAND_LIST[48] = &Scripts::cmdSetCycle; COMMAND_LIST[49] = &Scripts::cmdCycle; COMMAND_LIST[50] = &Scripts::cmdCharSpeak; COMMAND_LIST[51] = &Scripts::cmdTexSpeak; COMMAND_LIST[52] = &Scripts::cmdTexChoice; COMMAND_LIST[53] = &Scripts::cmdWait; COMMAND_LIST[54] = &Scripts::cmdSetConPos; COMMAND_LIST[55] = &Scripts::cmdCheckVFrame; COMMAND_LIST[56] = &Scripts::cmdJumpChoice; COMMAND_LIST[57] = &Scripts::cmdReturnChoice; COMMAND_LIST[58] = &Scripts::cmdClearBlock; COMMAND_LIST[59] = &Scripts::cmdLoadSound; COMMAND_LIST[60] = &Scripts::cmdFreeSound; COMMAND_LIST[61] = &Scripts::cmdSetVideoSound; COMMAND_LIST[62] = &Scripts::cmdPlayVideoSound; COMMAND_LIST[63] = &Scripts::cmdPrintWatch; COMMAND_LIST[64] = &Scripts::cmdDispAbout; COMMAND_LIST[65] = &Scripts::cmdPushLocation; COMMAND_LIST[66] = &Scripts::cmdCheckTravel; COMMAND_LIST[67] = &Scripts::cmdBlock; COMMAND_LIST[68] = &Scripts::cmdPlayerOff; COMMAND_LIST[69] = &Scripts::cmdPlayerOn; COMMAND_LIST[70] = &Scripts::cmdDead; COMMAND_LIST[71] = &Scripts::cmdFadeOut; COMMAND_LIST[72] = &Scripts::cmdEndVideo; COMMAND_LIST[73] = &Scripts::cmdHelp_v1; } void Scripts::setOpcodes_v2() { COMMAND_LIST[9] = &Scripts::cmdPrint_v2; COMMAND_LIST[15] = &Scripts::cmdSetInventory; COMMAND_LIST[28] = &Scripts::cmdDispInv_v2; COMMAND_LIST[29] = &Scripts::cmdSetTimer; COMMAND_LIST[32] = &Scripts::cmdJumpGoto; COMMAND_LIST[40] = &Scripts::cmdVideoEnded; COMMAND_LIST[45] = COMMAND_LIST[46] = &Scripts::cmdSpecial; COMMAND_LIST[63] = COMMAND_LIST[64] = COMMAND_LIST[66] = COMMAND_LIST[67] = &Scripts::cmdPushLocation; } void Scripts::setScript(Resource *res, bool restartFlag) { _resource = res; _data = res->_stream; _endFlag = restartFlag; } void Scripts::freeScriptData() { delete _resource; _resource = nullptr; _data = nullptr; } void Scripts::searchForSequence() { assert(_data); _data->seek(0); int sequenceId; do { while (_data->readByte() != SCRIPT_START_BYTE) {} sequenceId = _data->readUint16LE(); } while (sequenceId != _sequence); } void Scripts::charLoop() { bool endFlag = _endFlag; int pos = _data->pos(); _sequence = 2000; searchForSequence(); _vm->_images.clear(); _vm->_buffer2.copyBlock(&_vm->_buffer1, Common::Rect(0, 0, _vm->_buffer2.w, _vm->_buffer2.h)); _vm->_newRects.clear(); executeScript(); _vm->plotList1(); _vm->copyBlocks(); _data->seek(pos); _endFlag = endFlag; } void Scripts::clearWatch() { _vm->_events->hideCursor(); _vm->_screen->_orgX1 = 128; _vm->_screen->_orgY1 = 57; _vm->_screen->_orgX2 = 228; _vm->_screen->_orgY2 = 106; _vm->_screen->_lColor = 0; _vm->_screen->drawRect(); _vm->_events->showCursor(); } void Scripts::printWatch() { _vm->_fonts._charSet._lo = 8; _vm->_fonts._charSet._hi = 2; _vm->_fonts._charFor._lo = 2; _vm->_fonts._charFor._hi = 255; _vm->_screen->_maxChars = 19; _vm->_screen->_printOrg = Common::Point(128, 58); _vm->_screen->_printStart = Common::Point(128, 58); clearWatch(); Common::String msg = readString(); Common::String line = ""; int width = 0; bool lastLine; do { lastLine = _vm->_fonts._font2->getLine(msg, _vm->_screen->_maxChars * 6, line, width); // Draw the text _vm->_bubbleBox->printString(line); _vm->_screen->_printOrg.y += 6; _vm->_screen->_printOrg.x = _vm->_screen->_printStart.x; if (_vm->_screen->_printOrg.y == 106) { _vm->_events->waitKeyMouse(); clearWatch(); _vm->_screen->_printOrg.y = _vm->_screen->_printStart.y; } } while (!lastLine); _vm->_events->waitKeyMouse(); } void Scripts::findNull() { // No implementation required in ScummVM, the strings in the script files are already skipped by the use of readByte() } int Scripts::executeScript() { assert(_data); _endFlag = false; _returnCode = 0; do { // Get next command, skipping over script start start if it's being pointed to while ((_scriptCommand = _data->readByte()) == SCRIPT_START_BYTE) _data->skip(2); if (_scriptCommand < 0x80) error("Unexpected opcode value %d", _scriptCommand); executeCommand(_scriptCommand - 0x80); } while (!_endFlag && !_vm->shouldQuitOrRestart()); return _returnCode; } void Scripts::executeCommand(int commandIndex) { (this->*COMMAND_LIST[commandIndex])(); } void Scripts::cmdObject() { _vm->_bubbleBox->load(_data); } void Scripts::cmdEndObject() { printString(GENERAL_MESSAGES[_vm->_room->_selectCommand]); } void Scripts::cmdJumpLook() { if (_vm->_room->_selectCommand == 0) cmdGoto(); else _data->skip(2); } void Scripts::cmdJumpHelp() { if (_vm->_room->_selectCommand == 8) cmdGoto(); else _data->skip(2); } void Scripts::cmdJumpGet() { if (_vm->_room->_selectCommand == 3) cmdGoto(); else _data->skip(2); } void Scripts::cmdJumpMove() { if (_vm->_room->_selectCommand == 2) cmdGoto(); else _data->skip(2); } void Scripts::cmdJumpUse() { if (_vm->_room->_selectCommand == 4) cmdGoto(); else _data->skip(2); } void Scripts::cmdJumpTalk() { if (_vm->_room->_selectCommand == 6) cmdGoto(); else _data->skip(2); } void Scripts::cmdNull() { } #define PRINT_TIMER 25 void Scripts::cmdPrint_v2() { // Get a text line for display Common::String msg = readString(); printString(msg); } void Scripts::doCmdPrint_v1(Common::String msg) { _vm->_screen->_printOrg = Common::Point(20, 42); _vm->_screen->_printStart = Common::Point(20, 32); _vm->_bubbleBox->placeBubble(msg); _vm->_events->waitKeyMouse(); _vm->_events->hideCursor(); _vm->_screen->restoreBlock(); _vm->_events->showCursor(); findNull(); } void Scripts::cmdPrint_v1() { Common::String msg = readString(); doCmdPrint_v1(msg); } void Scripts::printString(const Common::String &msg) { if (_vm->getGameID() != GType_MartianMemorandum) { _vm->_screen->_printOrg = Common::Point(20, 42); _vm->_screen->_printStart = Common::Point(20, 42); _vm->_timers[PRINT_TIMER]._timer = 50; _vm->_timers[PRINT_TIMER]._initTm = 50; ++_vm->_timers[PRINT_TIMER]._flag; } // Display the text in a bubble, and wait for a keypress or mouse click _vm->_bubbleBox->placeBubble(msg); _vm->_events->waitKeyMouse(); // Wait until the bubble display is expired while (!_vm->shouldQuit() && _vm->_timers[PRINT_TIMER]._flag) { _vm->_events->pollEvents(); } // Restore the original screen over the text bubble _vm->_screen->restoreBlock(); } Common::String Scripts::readString() { Common::String msg; byte c; while ((c = (char)_data->readByte()) != '\0') msg += c; return msg; } void Scripts::cmdRetPos() { _endFlag = true; _returnCode = 0; } void Scripts::cmdAnim() { int animId = _data->readByte(); _vm->_animation->animate(animId); } void Scripts::cmdSetFlag() { int flagNum = _data->readByte(); byte flagVal = _data->readByte(); assert(flagNum < 256); _vm->_flags[flagNum] = flagVal; } void Scripts::cmdCheckFlag() { int flagNum = _data->readUint16LE(); int flagVal = _data->readUint16LE(); assert(flagNum < 256); if (_vm->_flags[flagNum] == flagVal) cmdGoto(); else _data->skip(2); } void Scripts::cmdGoto() { _sequence = _data->readUint16LE(); searchForSequence(); } void Scripts::cmdAddScore() { _data->skip(1); } void Scripts::cmdSetInventory() { int itemId = _data->readByte(); int itemVal = _data->readByte(); (*_vm->_inventory)[itemId] = itemVal; _vm->_inventory->_startInvItem = 0; _vm->_inventory->_startInvBox = 0; _vm->_inventory->_invChangeFlag = true; } void Scripts::cmdCheckInventory() { int itemId = _data->readUint16LE(); int itemVal = _data->readUint16LE(); if ((*_vm->_inventory)[itemId] == itemVal) cmdGoto(); else _data->skip(2); } void Scripts::cmdSetTex() { _vm->_player->_playerDirection = RIGHT; int posX = _data->readSint16LE() - (_vm->_player->_playerOffset.x / 2); if (posX <= _vm->_player->_rawPlayer.x) _vm->_player->_playerDirection = LEFT; _vm->_player->_rawPlayer.x = posX; _vm->_player->checkScroll(); bool scrlTemp = _vm->_player->_scrollFlag; _vm->_player->_playerDirection = UP; int posY = _data->readSint16LE(); if (posY <= _vm->_player->_rawPlayer.y) _vm->_player->_playerDirection = DOWN; _vm->_player->_rawPlayer.y = posY; _vm->_player->_frame = 5; _vm->_player->checkScroll(); _vm->_player->_scrollFlag |= scrlTemp; _vm->_player->_position = Common::Point(_vm->_player->_rawPlayer.x, _vm->_player->_rawPlayer.y - _vm->_player->_playerOffset.y); _vm->_player->_offsetY = _vm->_player->_playerOffset.y; _vm->_player->_spritesPtr = _vm->_player->_playerSprites; _vm->_player->_frameNumber = _vm->_player->_frame; _vm->_room->setWallCodes(); } #define CURRENT_ROOM 0xFF void Scripts::cmdNewRoom() { int roomNumber = _data->readByte(); if (roomNumber != CURRENT_ROOM) _vm->_player->_roomNumber = roomNumber; _vm->_room->_function = FN_CLEAR1; _vm->freeChar(); _vm->_converseMode = 0; cmdRetPos(); } void Scripts::converse1(int val) { _vm->_conversation = val; _vm->_room->clearRoom(); _vm->freeChar(); _vm->_char->loadChar(_vm->_conversation); _vm->_events->setCursor(CURSOR_ARROW); _vm->_images.clear(); _vm->_oldRects.clear(); _sequence = 0; searchForSequence(); if (_vm->_screen->_vesaMode) { _vm->_converseMode = 1; } } void Scripts::cmdConverse() { int val = _data->readUint16LE(); converse1(val); } void Scripts::cmdCheckFrame() { int id = _data->readUint16LE(); Animation *anim = _vm->_animation->findAnimation(id); int frame = _data->readUint16LE(); if (anim->_frameNumber == frame) cmdGoto(); else _data->skip(2); } void Scripts::cmdCheckAnim() { int id = _data->readUint16LE(); Animation *anim = _vm->_animation->findAnimation(id); if (anim->_currentLoopCount == -1) cmdGoto(); else _data->skip(2); } void Scripts::cmdSnd() { int id = _data->readByte(); _vm->_sound->playSound(id); } void Scripts::cmdRetNeg() { _endFlag = true; _returnCode = -1; } void Scripts::cmdCheckLoc() { int minX = _data->readUint16LE(); int minY = _data->readUint16LE(); int maxX = _data->readUint16LE(); int maxY = _data->readUint16LE(); int curX = _vm->_player->_rawPlayer.x + _vm->_player->_playerOffset.x; int curY = _vm->_player->_rawPlayer.y; if ((curX >= minX) && (curX <= maxX) && (curY >= minY) && (curY <= maxY)) cmdGoto(); else _data->skip(2); } void Scripts::cmdSetAnim() { int animId = _data->readByte(); Animation *anim = _vm->_animation->setAnimation(animId); if (anim) _vm->_animation->setAnimTimer(anim); } void Scripts::cmdDispInv_v1() { _vm->_inventory->displayInv(); } void Scripts::cmdDispInv_v2() { _vm->_inventory->newDisplayInv(); _vm->_events->forceSetCursor(CURSOR_ARROW); } void Scripts::cmdSetAbout() { int idx = _data->readByte(); int val = _data->readByte(); _vm->_ask[idx] = val; _vm->_startAboutBox = _vm->_startAboutItem = 0; } void Scripts::cmdSetTimer() { int idx = _data->readUint16LE(); int val = _data->readUint16LE(); ++_vm->_timers[idx]._flag; _vm->_timers[idx]._timer = val; _vm->_timers[idx]._initTm = val; _vm->_events->debounceLeft(); _vm->_events->zeroKeys(); } void Scripts::cmdCheckTimer() { int idx = _data->readUint16LE(); _vm->_canSaveLoad = true; _vm->_events->pollEvents(); _vm->_canSaveLoad = false; // Since the ScummVM debugger can be launched from the above point, we need // to check whether the script needs to be ended here, since some commands, // like the scene command, can change the current script if (_endFlag) return; if ((idx == 9) && _vm->_events->isKeyPending()) { _vm->_events->zeroKeys(); _vm->_timers[9]._timer = 0; _vm->_timers[9]._flag = 0; } int val = _data->readUint16LE() & 0xFF; if (_vm->_timers[idx]._flag == val) cmdGoto(); else _data->skip(2); } void Scripts::cmdSetTravel() { int idx = _data->readByte(); int dest = _data->readByte(); _vm->_travel[idx] = dest; _vm->_startTravelItem = _vm->_startTravelBox = 0; } void Scripts::cmdJumpGoto() { if (_vm->_room->_selectCommand == 5) cmdGoto(); else _data->skip(2); } void Scripts::cmdSetVideo() { Common::Point pt; pt.x = _data->readSint16LE(); pt.y = _data->readSint16LE(); int cellIndex = _data->readUint16LE(); int rate = _data->readUint16LE(); _vm->_video->setVideo(_vm->_screen, pt, _vm->_extraCells[cellIndex]._vid, rate); } void Scripts::cmdPlayVideo() { _vm->_video->playVideo(); } void Scripts::cmdPlotImage() { _vm->_destIn = _vm->_current; int destX = _data->readUint16LE(); int destY = _data->readUint16LE(); int objId = _data->readUint16LE(); int imgId = _data->readUint16LE(); _vm->_screen->plotImage(_vm->_objectsTable[objId], imgId, Common::Point(destX, destY)); } void Scripts::cmdSetDisplay() { _vm->_screen->setDisplayScan(); _vm->_current = _vm->_screen; } void Scripts::cmdSetBuffer() { _vm->_current = &_vm->_buffer2; } void Scripts::cmdSetScroll() { _vm->_scrollCol = _data->readUint16LE(); _vm->_scrollRow = _data->readUint16LE(); _vm->_scrollX = 0; _vm->_scrollY = 0; } void Scripts::cmdSaveRect() { int x = _vm->_screen->_lastBoundsX; int y = _vm->_screen->_lastBoundsY; int w = _vm->_screen->_lastBoundsW; int h = _vm->_screen->_lastBoundsH; _vm->_newRects.push_back(Common::Rect(x, y, x + w, x + h)); } void Scripts::cmdVideoEnded() { _vm->_events->pollEventsAndWait(); if (_vm->_video->_videoEnd) { cmdGoto(); } else { _data->skip(2); } } void Scripts::cmdSetBufVid() { _vm->_vidX = _data->readUint16LE(); _vm->_vidY = _data->readUint16LE(); int idx = _data->readUint16LE(); int rate = _data->readUint16LE(); _vm->_video->setVideo(&_vm->_vidBuf, Common::Point(0, 0), FileIdent(_vm->_extraCells[idx]._vid._fileNum, _vm->_extraCells[idx]._vid._subfile), rate); } void Scripts::cmdPlayBufVid() { _vm->_video->playVideo(); _vm->_video->copyVideo(); } void Scripts::cmdRemoveLast() { --_vm->_numAnimTimers; } void Scripts::cmdDoTravel() { while (true) { _vm->_travelBox->getList(Martian::TRAVDATA, _vm->_travel); int btnSelected = 0; int boxX = _vm->_travelBox->doBox_v1(_vm->_startTravelItem, _vm->_startTravelBox, btnSelected); _vm->_startTravelItem = _vm->_boxDataStart; _vm->_startTravelBox = _vm->_boxSelectY; if (boxX == -1) btnSelected = 2; if (btnSelected != 2) { int idx = _vm->_travelBox->_tempListIdx[boxX]; if (Martian::_byte1EEB5[idx] != _vm->_byte26CB5) { _vm->_bubbleBox->_bubbleTitle = "_travel"; _vm->_bubbleBox->printString(_vm->_res->CANT_GET_THERE); continue; } if (_vm->_player->_roomNumber != idx) { _vm->_player->_roomNumber = idx; _vm->_room->_function = FN_CLEAR1; if (_vm->_res->ROOMTBL[idx]._travelPos.x == -1) { // For x == -1, the y value is a script Id, not a co-ordinate _vm->_player->_roomNumber = idx; _vm->_room->_conFlag = true; _vm->_scripts->converse1(_vm->_res->ROOMTBL[idx]._travelPos.y); return; } _vm->_player->_rawPlayer = _vm->_res->ROOMTBL[idx]._travelPos; cmdRetPos(); return; } } if (_vm->_player->_roomNumber == -1) continue; return; } } void Scripts::cmdHelp_v1() { int idx = 0; for (int i = 0; i < 40; i++) { byte c = _data->readByte(); if (c != 0xFF) { Common::String tmpStr = c + readString(); if (Martian::HELP[i]) { _vm->_helpBox->_tempList[idx] = tmpStr; _vm->_helpBox->_tempListIdx[idx] = i; ++idx; } } else break; } _vm->_helpBox->_tempList[idx] = ""; int btnSelected = 0; int boxX = _vm->_helpBox->doBox_v1(0, 0, btnSelected); if (boxX == -1) btnSelected = 2; if (btnSelected != 2) _vm->_useItem = _vm->_helpBox->_tempListIdx[boxX]; else _vm->_useItem = -1; } void Scripts::cmdCheckAbout() { int idx = _data->readSint16LE(); int val = _data->readSint16LE(); if (_vm->_ask[idx] == val) cmdGoto(); else _data->skip(2); } void Scripts::cmdSpecial() { _specialFunction = _data->readUint16LE(); int p1 = _data->readUint16LE(); int p2 = _data->readUint16LE(); if (_specialFunction == 1) { if (_vm->_establishTable[p2]) return; _vm->_screen->savePalette(); } executeSpecial(_specialFunction, p1, p2); if (_specialFunction == 1) { _vm->_screen->restorePalette(); _vm->_room->_function = FN_RELOAD; // WORKAROUND: This fixes scene establishment being re-shown // when restoring savegames in rooms which have one if (_vm->getGameID() == GType_Amazon && !_vm->isCD()) _vm->_establishTable[p2] = true; } } void Scripts::cmdSetCycle() { int startCycle = _data->readUint16LE(); int endCycle = _data->readUint16LE(); int timer = _data->readUint16LE(); _vm->_screen->setPaletteCycle(startCycle, endCycle, timer); } void Scripts::cmdCycle() { if (_vm->_startup == -1) _vm->_screen->cyclePaletteForward(); } void Scripts::cmdCharSpeak() { _vm->_screen->_printOrg = _charsOrg; _vm->_screen->_printStart = _charsOrg; byte v; Common::String tmpStr = ""; while ((v = _data->readByte()) != 0) tmpStr += (char)v; _vm->_bubbleBox->placeBubble(tmpStr); findNull(); } void Scripts::cmdTexSpeak() { _vm->_screen->_printOrg = _texsOrg; _vm->_screen->_printStart = _texsOrg; _vm->_screen->_maxChars = (_vm->getGameID() == GType_MartianMemorandum) ? 23 : 20; byte v; Common::String tmpStr = ""; while ((v = _data->readByte()) != 0) tmpStr += (char)v; if (_vm->getGameID() == GType_MartianMemorandum) _vm->_bubbleBox->_bubbleDisplStr = Common::String("TEX"); else _vm->_bubbleBox->_bubbleDisplStr = Common::String("JASON"); _vm->_bubbleBox->placeBubble1(tmpStr); findNull(); } #define BTN_COUNT 6 void Scripts::cmdTexChoice() { // MM is defining 2 times the last range in the original. static const int BTN_RANGES_v1[BTN_COUNT][2] = { { 0, 60 }, { 64, 124 }, { 129, 192 }, { 194, 227 }, { 233, 292 }, { 297, 319 } }; static const int BTN_RANGES_v2[BTN_COUNT][2] = { { 0, 76 }, { 77, 154 }, { 155, 232 }, { 233, 276 }, { 0, 0 }, { 277, 319 } }; _vm->_oldRects.clear(); _choiceStart = _data->pos() - 1; _vm->_fonts._charSet._lo = 1; _vm->_fonts._charSet._hi = 8; _vm->_fonts._charFor._hi = 255; if (_vm->getGameID() == GType_MartianMemorandum) { _vm->_fonts._charFor._lo = 247; _vm->_screen->_maxChars = 23; } else { _vm->_fonts._charFor._lo = 55; _vm->_screen->_maxChars = 20; } _vm->_screen->_printOrg = _texsOrg; _vm->_screen->_printStart = _texsOrg; _vm->_bubbleBox->clearBubbles(); _vm->_bubbleBox->_bubbleDisplStr = Common::String("RESPONSE 1"); byte v; Common::String tmpStr = ""; while ((v = _data->readByte()) != 0) tmpStr += (char)v; _vm->_bubbleBox->calcBubble(tmpStr); _vm->_bubbleBox->printBubble(tmpStr); Common::Array responseCoords; responseCoords.push_back(_vm->_bubbleBox->_bounds); _vm->_screen->_printOrg.y = _vm->_bubbleBox->_bounds.bottom + ((_vm->getGameID() == GType_MartianMemorandum) ? 20 : 11); findNull(); tmpStr.clear(); while ((v = _data->readByte()) != 0) tmpStr += (char)v; if (tmpStr.size() != 0) { _vm->_bubbleBox->_bubbleDisplStr = Common::String("RESPONSE 2"); _vm->_bubbleBox->calcBubble(tmpStr); _vm->_bubbleBox->printBubble(tmpStr); responseCoords.push_back(_vm->_bubbleBox->_bounds); _vm->_screen->_printOrg.y = _vm->_bubbleBox->_bounds.bottom + ((_vm->getGameID() == GType_MartianMemorandum) ? 20 : 11); } findNull(); bool choice3Fl = false; tmpStr.clear(); while ((v = _data->readByte()) != 0) tmpStr += (char)v; if (tmpStr.size() != 0) { _vm->_bubbleBox->_bubbleDisplStr = Common::String("RESPONSE 3"); _vm->_bubbleBox->calcBubble(tmpStr); _vm->_bubbleBox->printBubble(tmpStr); responseCoords.push_back(_vm->_bubbleBox->_bounds); _vm->_screen->_printOrg.y = _vm->_bubbleBox->_bounds.bottom + ((_vm->getGameID() == GType_MartianMemorandum) ? 20 : 11); } findNull(); int choice = -1; do { _vm->_events->pollEvents(); if (_vm->shouldQuit()) return; charLoop(); _vm->_bubbleBox->_bubbleDisplStr = _vm->_bubbleBox->_bubbleTitle; if (_vm->_events->_leftButton) { if (_vm->_events->_mouseRow >= ((_vm->getGameID() == GType_MartianMemorandum) ? 23 : 22)) { _vm->_events->debounceLeft(); int x = _vm->_events->_mousePos.x; for (int i = 0; i < BTN_COUNT; i++) { if (((_vm->getGameID() == GType_MartianMemorandum) && (x >= BTN_RANGES_v1[i][0]) && (x < BTN_RANGES_v1[i][1])) || ((_vm->getGameID() == GType_Amazon) && (x >= BTN_RANGES_v2[i][0]) && (x < BTN_RANGES_v2[i][1]))) { choice = i; break; } } } else { _vm->_events->debounceLeft(); choice = _vm->_events->checkMouseBox1(responseCoords); } } } while ((choice == -1) || ((choice == 2) && choice3Fl)); _choice = choice + 1; _vm->_bubbleBox->clearBubbles(); } void Scripts::cmdWait() { int time = _data->readSint16LE(); _vm->_timers[3]._timer = time; _vm->_timers[3]._initTm = time; _vm->_timers[3]._flag++; _vm->_events->zeroKeys(); while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() && _vm->_timers[3]._flag) { _vm->_midi->midiRepeat(); charLoop(); _vm->_events->pollEventsAndWait(); } _vm->_events->debounceLeft(); _vm->_events->zeroKeys(); } void Scripts::cmdSetConPos() { int x = _data->readSint16LE(); int y = _data->readSint16LE(); _charsOrg = Common::Point(x, y); x = _data->readSint16LE(); y = _data->readSint16LE(); _texsOrg = Common::Point(x, y); } void Scripts::cmdCheckVFrame() { if (_vm->_video->_videoFrame == _data->readSint16LE()) cmdGoto(); else _data->skip(2); } void Scripts::cmdJumpChoice() { int val = (_data->readUint16LE() & 0xFF); if (val == _choice) { _sequence = _data->readUint16LE(); searchForSequence(); } else _data->skip(2); } void Scripts::cmdReturnChoice() { _data->seek(_choiceStart); } void Scripts::cmdClearBlock() { _vm->_screen->restoreBlock(); } void Scripts::cmdLoadSound() { int idx = _data->readSint16LE(); _vm->_sound->_soundTable.clear(); Resource *sound = _vm->_files->loadFile(_vm->_extraCells[idx]._vidSound); _vm->_sound->_soundTable.push_back(SoundEntry(sound, 1)); } void Scripts::cmdFreeSound() { SoundManager &sound = *_vm->_sound; if (sound._soundTable.size() > 0 && sound._soundTable[0]._res) { // Keep doing char display loop if playing sound for it do { if (_vm->_flags[236] == 1) charLoop(); _vm->_events->pollEvents(); } while (!_vm->shouldQuit() && sound.isSFXPlaying()); // Free the sounds sound.freeSounds(); } } void Scripts::cmdSetVideoSound() { uint32 startPos = _data->pos(); _data->skip(4); cmdLoadSound(); _data->seek(startPos); cmdSetVideo(); _vm->_video->_soundFrame = _data->readUint16LE(); _vm->_video->_soundFlag = false; } void Scripts::cmdPlayVideoSound() { _vm->_video->playVideo(); if (_vm->_video->_soundFrame == _vm->_video->_videoFrame && !_vm->_video->_soundFlag) { _vm->_sound->playSound(0); _vm->_video->_soundFlag = true; } _vm->_events->pollEventsAndWait(); } void Scripts::cmdPrintWatch() { printWatch(); findNull(); } void Scripts::cmdDispAbout() { _vm->_travelBox->getList(Martian::ASK_TBL, _vm->_ask); int btnSelected = 0; int boxX = _vm->_aboutBox->doBox_v1(_vm->_startAboutItem, _vm->_startAboutBox, btnSelected); _vm->_startAboutItem = _vm->_boxDataStart; _vm->_startAboutBox = _vm->_boxSelectY; if (boxX == -1) btnSelected = 2; if (btnSelected == 2) _vm->_useItem = -1; else _vm->_useItem = _vm->_travelBox->_tempListIdx[boxX]; } void Scripts::cmdPushLocation() { _choiceStart = _data->pos() - 1; } void Scripts::cmdCheckTravel() { int idx = _data->readSint16LE(); int val = _data->readUint16LE(); if (_vm->_travel[idx] == val) cmdGoto(); else _data->skip(2); } void Scripts::cmdBlock() { error("TODO: cmdBlock"); /*int val1 = */_data->readSint16LE(); /*int val2 = */_data->readUint16LE(); /*int val3 = */_data->readSint16LE(); /*int val4 = */_data->readUint16LE(); } void Scripts::cmdPlayerOff() { _vm->_player->_playerOff = true; } void Scripts::cmdPlayerOn() { _vm->_player->_playerOff = false; } void Scripts::cmdDead() { int deathId = _data->readByte(); _vm->dead(deathId); } void Scripts::cmdFadeOut() { _vm->_screen->forceFadeOut(); } void Scripts::cmdEndVideo() { _vm->_video->closeVideo(); _vm->_video->_videoEnd = true; } } // End of namespace Access