diff options
87 files changed, 1523 insertions, 246 deletions
@@ -38,6 +38,13 @@ For a more comprehensive changelog of the latest experimental code, see: Gob: - Fixed lock up for some games during sound initialization. + KYRA: + - Fixed potential crash when using swamp snake potion on the rat in Hand + of Fate. (NOTE: This fix was included in version 1.8.0, but it was not + added to the NEWS file). + - Fixed missing voice reactions when hitting enemies in CD version of + Lands of Lore. + Lab: - Fixed lock-up during ending sequence. - Improved internal game controls. diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 685ee99e6f..d536429f4e 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -1043,12 +1043,12 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) { if (value & 0x10) { _timers[0].smpTillCb = _timers[0].smpPerCb; - _timers[0].smpTillCbRem = _timers[0].smpTillCbRem; + _timers[0].smpTillCbRem = _timers[0].smpPerCbRem; } if (value & 0x20) { _timers[1].smpTillCb = _timers[1].smpPerCb; - _timers[1].smpTillCbRem = _timers[1].smpTillCbRem; + _timers[1].smpTillCbRem = _timers[1].smpPerCbRem; } } else if (l == 2) { // LFO diff --git a/backends/graphics/opengl/pipelines/shader.cpp b/backends/graphics/opengl/pipelines/shader.cpp index 8e38458f73..a2dabb7c22 100644 --- a/backends/graphics/opengl/pipelines/shader.cpp +++ b/backends/graphics/opengl/pipelines/shader.cpp @@ -56,6 +56,8 @@ void ShaderPipeline::activateInternal() { } _activeShader->activate(); + + GL_CALL(glVertexAttribPointer(_colorAttribLocation, 4, GL_FLOAT, GL_FALSE, 0, _colorAttributes)); } void ShaderPipeline::deactivateInternal() { @@ -74,8 +76,6 @@ void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { *dst++ = b; *dst++ = a; } - - GL_CALL(glVertexAttribPointer(_colorAttribLocation, 4, GL_FLOAT, GL_FALSE, 0, _colorAttributes)); } void ShaderPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates) { diff --git a/backends/graphics/opengl/shader.cpp b/backends/graphics/opengl/shader.cpp index 27981f25dc..0b4c677d70 100644 --- a/backends/graphics/opengl/shader.cpp +++ b/backends/graphics/opengl/shader.cpp @@ -37,7 +37,7 @@ namespace { #pragma mark - Builtin Shader Sources - -const char *const g_defaultVertexShader = +const char *const g_defaultVertexShader = "attribute vec4 position;\n" "attribute vec2 texCoordIn;\n" "attribute vec4 blendColorIn;\n" @@ -286,6 +286,9 @@ GLshader Shader::compileShader(const char *source, GLenum shaderType) { } ShaderManager::ShaderManager() : _initializeShaders(true) { + for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) { + _builtIn[i] = nullptr; + } } ShaderManager::~ShaderManager() { diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 8b94549971..33598b5488 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -509,6 +509,7 @@ TextureCLUT8GPU::TextureCLUT8GPU() // Setup pipeline. _clut8Pipeline->setFramebuffer(_target); _clut8Pipeline->setPaletteTexture(&_paletteTexture); + _clut8Pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f); } TextureCLUT8GPU::~TextureCLUT8GPU() { diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt index 235986a878..92754a27b4 100644 --- a/devtools/scumm-md5.txt +++ b/devtools/scumm-md5.txt @@ -237,6 +237,7 @@ monkey The Secret of Monkey Island 71523b539491527d9860f4407faf0411 7607 en DOS Demo EGA Demo - Fingolfin 771bc18ec6f93837b839c992b211904b -1 de DOS Demo EGA Demo - khalek 54a936ad06161ff7bfefcb96200f7bff 7617 en Amiga VGA VGA Demo - khalek + c0c9de81fb965e6cbe77f6e5631ca705 9135 en DOS SE Talkie Unofficial SE Talkie v1.02 rootfather pass Passport to Adventure e6cd81b25ab1453a8a6d3482118c391e 7857 en DOS - - v1.0 9/14/90 Fingolfin @@ -269,6 +270,7 @@ monkey2 Monkey Island 2: LeChuck's Revenge 430bc518017b6fac046f58bab6baad5d -1 jp FM-TOWNS FM-TOWNS - - Antti Leimi, Andrea Petrucci 387a544b8b10b26912d8413bab63a853 -1 en DOS - Demo non-interactive khalek + f4d20ab4ce19743a646cb48bd93aee72 10835 en DOS SE Talkie Unofficial SE Talkie v0.2 rootfather atlantis Indiana Jones and the Fate of Atlantis 3a03dab514e4038df192d8a8de469788 -1 en Amiga Floppy Floppy - dhewg diff --git a/doc/de/Neues b/doc/de/Neues index 530e2270f8..e3d8f3a607 100644 --- a/doc/de/Neues +++ b/doc/de/Neues @@ -40,6 +40,14 @@ Programmcodes finden Sie auf Englisch unter: Gob: - Aufhängen während Sound-Initialisierung in mehreren Spielen behoben. + KYRA: + - Potentieller Absturz behoben, der in "Hand of Fate" auftritt, wenn der + Sumpfschlangentrank an der Ratte verwendet wird. + (HINWEIS: Dieser Fehler wurde bereits in Version 1.8.0 behoben, + jedoch nicht in der Neues-Datei erwähnt). + - Fehlende Stimm-Reaktionen korrigiert, wenn Gegner in der CD-Version von + Lands of Lore getroffen wurden. + Lab: - Aufhängen während der End-Sequenz behoben. - Interne Spiel-Bedienelemente verbessert. diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index e566ad12f6..60c8d1f3ef 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -403,6 +403,11 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _lastSaveTime = 0; + _playTimeInSecondsAdjust = 0; + _lastUsedPlayTimeInCycles = 0; + _lastUsedPlayTimeInSeconds = 0; + _passedPlayTimeCycles = 0; + memset(_keyQueue, 0, sizeof(_keyQueue)); _console = nullptr; @@ -418,6 +423,9 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _inventory = nullptr; _keyHoldMode = false; + + _artificialDelayCurrentRoom = 0; + _artificialDelayCurrentPicture = 0; } void AgiEngine::initialize() { diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index fed07ea986..8a62fce86c 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -662,7 +662,7 @@ void cmdWordToString(AgiGame *state, AgiEngine *vm, uint8 *parameter) { uint16 stringNr = parameter[0]; uint16 wordNr = parameter[1]; - strcpy(state->strings[stringNr], state->_vm->_words->getEgoWord(wordNr)); + Common::strlcpy(state->strings[stringNr], state->_vm->_words->getEgoWord(wordNr), MAX_STRINGLEN); } void cmdOpenDialogue(AgiGame *state, AgiEngine *vm, uint8 *parameter) { @@ -2014,7 +2014,7 @@ void cmdGetString(AgiGame *state, AgiEngine *vm, uint8 *parameter) { // copy string to destination // TODO: not sure if set all the time or only when ENTER is pressed - strcpy(&state->_vm->_game.strings[stringDestNr][0], (char *)textMgr->_inputString); + Common::strlcpy(&state->_vm->_game.strings[stringDestNr][0], (char *)textMgr->_inputString, MAX_STRINGLEN); textMgr->charPos_Pop(); @@ -2102,7 +2102,7 @@ void cmdSetString(AgiGame *state, AgiEngine *vm, uint8 *parameter) { // CM: to avoid crash in Groza (str = 150) if (stringNr > MAX_STRINGS) return; - strcpy(state->strings[stringNr], state->_curLogic->texts[textNr]); + Common::strlcpy(state->strings[stringNr], state->_curLogic->texts[textNr], MAX_STRINGLEN); } void cmdDisplay(AgiGame *state, AgiEngine *vm, uint8 *parameter) { diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp index 4b215edc63..4505668fd1 100644 --- a/engines/agi/op_test.cpp +++ b/engines/agi/op_test.cpp @@ -231,8 +231,8 @@ uint8 AgiEngine::testCompareStrings(uint8 s1, uint8 s2) { char ms2[MAX_STRINGLEN]; int j, k, l; - strcpy(ms1, _game.strings[s1]); - strcpy(ms2, _game.strings[s2]); + Common::strlcpy(ms1, _game.strings[s1], MAX_STRINGLEN); + Common::strlcpy(ms2, _game.strings[s2], MAX_STRINGLEN); l = strlen(ms1); for (k = 0, j = 0; k < l; k++) { diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 620d5e0baf..e1545cdb68 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -1205,7 +1205,7 @@ void MickeyEngine::printStory() { clearScreen(IDA_DEFAULT); for (iRow = 0; iRow < 25; iRow++) { - strcpy(szLine, buffer + pBuf); + Common::strlcpy(szLine, buffer + pBuf, 41); drawStr(iRow, 0, IDA_DEFAULT, szLine); pBuf += strlen(szLine) + 1; } @@ -1213,7 +1213,7 @@ void MickeyEngine::printStory() { clearScreen(IDA_DEFAULT); for (iRow = 0; iRow < 21; iRow++) { - strcpy(szLine, buffer + pBuf); + Common::strlcpy(szLine, buffer + pBuf, 41); drawStr(iRow, 0, IDA_DEFAULT, szLine); pBuf += strlen(szLine) + 1; } diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index 87ac7c19c6..8fb9daca5e 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -292,7 +292,7 @@ int WinnieEngine::parser(int pc, int index, uint8 *buffer) { } // extract menu string - strcpy(szMenu, (char *)(buffer + pc)); + Common::strlcpy(szMenu, (char *)(buffer + pc), 121); XOR80(szMenu); break; default: diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index 0658609cd0..09fce9320b 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -118,7 +118,7 @@ int AgiEngine::saveGame(const Common::String &fileName, const Common::String &de out->writeByte(2); // was _game.state, 2 = STATE_RUNNING - strcpy(gameIDstring, _game.id); + Common::strlcpy(gameIDstring, _game.id, 8); out->write(gameIDstring, 8); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game id (%s, %s)", gameIDstring, _game.id); diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index 110ba10632..274a654547 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -457,7 +457,7 @@ void TextMgr::drawMessageBox(const char *textPtr, int16 forcedHeight, int16 want // Caller wants to force specified width/height? set it if (forcedHeight) _messageState.textSize_Height = forcedHeight; - + if (forcedWidth) { if (wantedWidth) _messageState.textSize_Width = wantedWidth; @@ -1207,7 +1207,7 @@ char *TextMgr::stringPrintf(const char *originalText) { } assert(resultString.size() < sizeof(resultPrintfBuffer)); - strcpy(resultPrintfBuffer, resultString.c_str()); + Common::strlcpy(resultPrintfBuffer, resultString.c_str(), 2000); return resultPrintfBuffer; } diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp index 4f6c62c48a..cc443f2f50 100644 --- a/engines/agos/string.cpp +++ b/engines/agos/string.cpp @@ -126,14 +126,14 @@ const byte *AGOSEngine::getStringPtrByID(uint16 stringId, bool upperCase) { _awaitTwoByteToken = 0; uncompressText(ptr); _textBuffer[_textCount] = 0; - strcpy((char *)dst, (const char *)_textBuffer); + Common::strlcpy((char *)dst, (const char *)_textBuffer, 180); } else { if (stringId < 0x8000) { stringPtr = _stringTabPtr[stringId]; } else { stringPtr = getLocalStringByID(stringId); } - strcpy((char *)dst, (const char *)stringPtr); + Common::strlcpy((char *)dst, (const char *)stringPtr, 180); } // WORKAROUND bug #1538873: The French version of Simon 1 and the @@ -796,7 +796,7 @@ void AGOSEngine_Feeble::printInteractText(uint16 num, const char *string) { if (*string2 == 0x00) { if (w == 0xFFFF) w = pixels; - strcpy(convertedString2, string); + Common::strlcpy(convertedString2, string, 320); break; } while (*string2 != ' ') { diff --git a/engines/agos/string_pn.cpp b/engines/agos/string_pn.cpp index 7a364f3ea9..06c8bbd98e 100644 --- a/engines/agos/string_pn.cpp +++ b/engines/agos/string_pn.cpp @@ -114,7 +114,7 @@ void AGOSEngine_PN::getObjectName(char *v, uint16 x) { } void AGOSEngine_PN::pcl(const char *s) { - strcat(_sb, s); + Common::strlcat(_sb, s, 80); if (strchr(s, '\n') == 0) { for (char *str = _sb; *str; str++) windowPutChar(_windowArray[_curWindow], *str); diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp index 54f5c00d93..8b0d8b6c77 100644 --- a/engines/cge2/vga13h.cpp +++ b/engines/cge2/vga13h.cpp @@ -952,8 +952,9 @@ uint8 Vga::closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 col } uint8 Vga::closest(Dac *pal, Dac x) { - int exp = (sizeof(long) * 8 - 1); - long D = (1 << exp) - 1; // Maximum value of long. + long D = 0; + D = ~D; + D = (unsigned long)D >> 1; // Maximum value of long. long R = x._r; long G = x._g; long B = x._b; diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp index 9515b552e1..4458e39e91 100644 --- a/engines/cruise/ctp.cpp +++ b/engines/cruise/ctp.cpp @@ -307,7 +307,7 @@ int initCt(const char *ctpName) { MemFree(ptr); if (ctpName != currentCtpName) - strcpy(currentCtpName, ctpName); + Common::strlcpy(currentCtpName, ctpName, 40); numberOfWalkboxes = segementSizeTable[6] / 2; // get the number of walkboxes diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp index 7a1258dbde..2eff82bc61 100644 --- a/engines/cruise/dataLoader.cpp +++ b/engines/cruise/dataLoader.cpp @@ -249,12 +249,19 @@ int loadFile(const char* name, int idx, int destIdx) { int numMaxEntriesInSet = getNumMaxEntiresInSet(ptr); if (destIdx > numMaxEntriesInSet) { + MemFree(ptr); return 0; // exit if limit is reached } - return loadSetEntry(name, ptr, destIdx, idx); + int res = loadSetEntry(name, ptr, destIdx, idx); + MemFree(ptr); + + return res; } case type_FNT: { - return loadFNTSub(ptr, idx); + int res = loadFNTSub(ptr, idx); + MemFree(ptr); + + return res; } case type_SPL: { // Sound file diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 8ee3b14d0c..36fbb73037 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -1576,6 +1576,9 @@ Movement::Movement(Movement *src, int *oldIdxs, int newSize, StaticANIObject *an _m2x = 0; _m2y = 0; + _counter = 0; + _counterMax = 0; + _field_78 = 0; _framePosOffsets = 0; _field_84 = 0; diff --git a/engines/lastexpress/entities/gendarmes.cpp b/engines/lastexpress/entities/gendarmes.cpp index b628b8dfe7..1b51dd2006 100644 --- a/engines/lastexpress/entities/gendarmes.cpp +++ b/engines/lastexpress/entities/gendarmes.cpp @@ -174,7 +174,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, doCompartment, CarIndex, EntityPosition) strcat((char *)¶meters1->seq1, (char *)¶ms->seq1); strcat((char *)¶meters1->seq2, (char *)¶ms->seq1); - strcat((char *)¶meters1->seq3, (char *)¶ms->seq1); + Common::strlcat((char *)¶meters1->seq3, (char *)¶ms->seq1, 9); // Beware, seq3 is smaller than seq1 if ((getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params->param1, (EntityPosition)params->param2) || getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params->param1, (EntityPosition)parameters2->param7) diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 697e6e1269..7308214551 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -366,7 +366,7 @@ void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) { assert(_name1.size() <= 16); assert(_name2.size() <= 16); - if (_name2.matchString("NISSND?") && (_status.status & kFlagType9) != kFlag3) { + if (_name2.matchString("NISSND?") && ((_status.status & kFlagType9) != kFlag3)) { s.syncAsUint32LE(_status.status); s.syncAsUint32LE(_type); s.syncAsUint32LE(_blockCount); // field_8; diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp index 38ca0ba54f..371bcd6ed6 100644 --- a/engines/lure/game.cpp +++ b/engines/lure/game.cpp @@ -538,7 +538,7 @@ void Game::handleRightClickMenu() { hotspot = res.getHotspot(room.hotspotId()); assert(hotspot); strings.getString(hotspot->nameId, statusLine); - strcat(statusLine, stringList.getString(S_FOR)); + Common::strlcat(statusLine, stringList.getString(S_FOR), MAX_DESC_SIZE); statusLine += strlen(statusLine); itemId = PopupMenu::ShowItems(GET, player->roomNumber()); @@ -549,7 +549,7 @@ void Game::handleRightClickMenu() { hotspot = res.getHotspot(room.hotspotId()); assert(hotspot); strings.getString(hotspot->nameId, statusLine); - strcat(statusLine, stringList.getString(S_TO)); + Common::strlcat(statusLine, stringList.getString(S_TO), MAX_DESC_SIZE); breakFlag = GetTellActions(); break; @@ -559,7 +559,7 @@ void Game::handleRightClickMenu() { case DRINK: hasItems = (res.numInventoryItems() != 0); if (!hasItems) - strcat(statusLine, stringList.getString(S_ACTION_NOTHING)); + Common::strlcat(statusLine, stringList.getString(S_ACTION_NOTHING), MAX_DESC_SIZE); statusLine += strlen(statusLine); room.update(); @@ -579,9 +579,9 @@ void Game::handleRightClickMenu() { assert(useHotspot); strings.getString(useHotspot->nameId, statusLine); if (action == GIVE) - strcat(statusLine, stringList.getString(S_TO)); + Common::strlcat(statusLine, stringList.getString(S_TO), MAX_DESC_SIZE); else - strcat(statusLine, stringList.getString(S_ON)); + Common::strlcat(statusLine, stringList.getString(S_ON), MAX_DESC_SIZE); statusLine += strlen(statusLine); } else if ((action == DRINK) || (action == EXAMINE)) diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp index fbf93e1e14..a972909b8b 100644 --- a/engines/lure/hotspots.cpp +++ b/engines/lure/hotspots.cpp @@ -1898,8 +1898,8 @@ void Hotspot::doStatus(HotspotData *hotspot) { endAction(); strings.getString(room.roomNumber(), buffer); - strcat(buffer, "\n\n"); - strcat(buffer, stringList.getString(S_YOU_ARE_CARRYING)); + Common::strlcat(buffer, "\n\n", MAX_DESC_SIZE); + Common::strlcat(buffer, stringList.getString(S_YOU_ARE_CARRYING), MAX_DESC_SIZE); // Scan through the list and add in any items assigned to the player HotspotDataList &list = res.hotspotData(); @@ -1909,25 +1909,25 @@ void Hotspot::doStatus(HotspotData *hotspot) { if (rec.roomNumber == PLAYER_ID) { if (numItems++ == 0) - strcat(buffer, ": "); + Common::strlcat(buffer, ": ", MAX_DESC_SIZE); else - strcat(buffer, ", "); + Common::strlcat(buffer, ", ", MAX_DESC_SIZE); strings.getString(rec.nameId, buffer + strlen(buffer)); } } // If there were no items, add in the word 'nothing' if (numItems == 0) - strcat(buffer, stringList.getString(S_INV_NOTHING)); + Common::strlcat(buffer, stringList.getString(S_INV_NOTHING), MAX_DESC_SIZE); // If the player has money, add it in uint16 numGroats = res.fieldList().numGroats(); if (numGroats > 0) { - strcat(buffer, "\n\n"); - strcat(buffer, stringList.getString(S_YOU_HAVE)); - sprintf(buffer + strlen(buffer), "%d", numGroats); - strcat(buffer, " "); - strcat(buffer, stringList.getString((numGroats == 1) ? S_GROAT : S_GROATS)); + Common::strlcat(buffer, "\n\n", MAX_DESC_SIZE); + Common::strlcat(buffer, stringList.getString(S_YOU_HAVE), MAX_DESC_SIZE); + snprintf(buffer + strlen(buffer), MAX_DESC_SIZE, "%d", numGroats); + Common::strlcat(buffer, " ", MAX_DESC_SIZE); + Common::strlcat(buffer, stringList.getString((numGroats == 1) ? S_GROAT : S_GROATS), MAX_DESC_SIZE); // Make sure we're not overrunning } // Display the dialog diff --git a/engines/lure/scripts.cpp b/engines/lure/scripts.cpp index 3df119a9da..f7dc06033a 100644 --- a/engines/lure/scripts.cpp +++ b/engines/lure/scripts.cpp @@ -926,8 +926,8 @@ uint16 Script::execute(uint16 startOffset) { opcode >>= 1; if (gDebugLevel >= ERROR_DETAILED) - strcat(debugInfo, (opcode > S_OPCODE_RANDOM) ? "INVALID" : - scriptOpcodes[opcode]); + Common::strlcat(debugInfo, (opcode > S_OPCODE_RANDOM) ? "INVALID" : + scriptOpcodes[opcode], MAX_DESC_SIZE); if (hasParam) { // Flag to read next two bytes as active parameter @@ -1087,7 +1087,7 @@ uint16 Script::execute(uint16 startOffset) { else if (scriptMethodNames[param] == NULL) strcat(debugInfo, " UNKNOWN METHOD"); else { strcat(debugInfo, " "); - strcat(debugInfo, scriptMethodNames[param]); + Common::strlcat(debugInfo, scriptMethodNames[param], MAX_DESC_SIZE); } // Any params diff --git a/engines/made/database.cpp b/engines/made/database.cpp index 3eab31acc2..0020cb398c 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -40,6 +40,7 @@ namespace Made { */ Object::Object() : _objData(NULL), _freeData(false) { + _objSize = 0; } Object::~Object() { diff --git a/engines/made/made.cpp b/engines/made/made.cpp index f1539297ee..a29aa2512f 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -58,11 +58,24 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng const GameSettings *g; + _eventNum = 0; + _eventMouseX = _eventMouseY = 0; + _eventKey = 0; + _autoStopSound = false; + _soundEnergyIndex = 0; + _soundEnergyArray = 0; + _musicBeatStart = 0; + _cdTimeStart = 0; + + _gameId = -1; + const char *gameid = ConfMan.get("gameid").c_str(); for (g = madeSettings; g->gameid; ++g) if (!scumm_stricmp(g->gameid, gameid)) _gameId = g->id; + assert(_gameId != -1); + _rnd = new Common::RandomSource("made"); _console = new MadeConsole(this); @@ -85,6 +98,8 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _music = nullptr; + _soundRate = 0; + // Set default sound frequency switch (getGameID()) { case GID_RODNEY: diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 453e2a4872..0beb132b93 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -223,7 +223,10 @@ bool PmvPlayer::play(const char *filename) { //delete _audioStream; delete _fd; - _surface->free(); + + if(_surface) + _surface->free(); + delete _surface; return !_aborted; diff --git a/engines/made/redreader.cpp b/engines/made/redreader.cpp index f92ffd8dd8..a0aaf7be43 100644 --- a/engines/made/redreader.cpp +++ b/engines/made/redreader.cpp @@ -102,7 +102,7 @@ int LzhDecompressor::decompress(Common::SeekableReadStream &source, byte *dest, int bufsize; byte* buffer; - buffer = (byte *) malloc(DICSIZ); + buffer = (byte *)calloc(DICSIZ, 1); _source = &source; _compSize = sourceLen; diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index f8e763e74e..a9734ed47d 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -43,6 +43,7 @@ Resource::~Resource() { PictureResource::PictureResource() : _picture(NULL), _picturePalette(NULL) { _hasPalette = false; + _paletteColorCount = 0; } PictureResource::~PictureResource() { @@ -182,6 +183,9 @@ void PictureResource::loadChunked(byte *source, int size) { /* AnimationResource */ AnimationResource::AnimationResource() { + _flags = 0; + _width = 0; + _height = 0; } AnimationResource::~AnimationResource() { diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index edccb68953..33edb3834c 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -91,6 +91,8 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _currentFontNum = 0; _fontDrawCtx.clipRect = Common::Rect(320, 200); _fontDrawCtx.destSurface = _backgroundScreen; + _outlineColor = 0; + _dropShadowColor = 0; clearChannels(); } diff --git a/engines/made/sound.cpp b/engines/made/sound.cpp index ad49031e7b..62559efa84 100644 --- a/engines/made/sound.cpp +++ b/engines/made/sound.cpp @@ -155,6 +155,7 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou }; soundEnergyItem.position = 0; + memset(deltaSoundBuffer, 0, 1024); if (soundEnergyArray) soundEnergyArray->clear(); @@ -237,6 +238,7 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou break; default: + delete[] soundBuffer; return; } @@ -247,6 +249,9 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou // soundBuffer. soundBuffer[workChunkSize] = soundBuffer[workChunkSize - 1]; + for (i = 0; i < chunkSize; i++) + soundBuffer[i] = 0; + if (deltaType == 1) { for (i = 0; i < chunkSize - 1; i += 2) { l = i / 2; diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 29bcd10094..5776d813cf 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -58,6 +58,7 @@ MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) : _resources = nullptr; _sound = nullptr; _audio = nullptr; + _screen = nullptr; } MADSEngine::~MADSEngine() { diff --git a/engines/mortevielle/mortevielle.cpp b/engines/mortevielle/mortevielle.cpp index 90d366ed7e..81b2edb57d 100644 --- a/engines/mortevielle/mortevielle.cpp +++ b/engines/mortevielle/mortevielle.cpp @@ -145,6 +145,7 @@ MortevielleEngine::MortevielleEngine(OSystem *system, const MortevielleGameDescr _endGame = false; _loseGame = false; _txxFileFl = false; + _is = 0; } MortevielleEngine::~MortevielleEngine() { diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index 50a5b38d8d..8f895f1532 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -163,7 +163,7 @@ int16 Program::findLocal(const char* name) { int16 Program::addLocal(const char *name, int16 value, int16 min, int16 max) { assert(_numLocals < NUM_LOCALS); - strcpy(_localNames[_numLocals], name); + Common::strlcpy(_localNames[_numLocals], name, 10); _locals[_numLocals].setRange(min, max); _locals[_numLocals].setValue(value); diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 2b75e78582..bbe759dffe 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -60,6 +60,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam DebugMan.addDebugChannel(kDebugMenu, "menu", "Menu debug level"); DebugMan.addDebugChannel(kDebugInventory, "inventory", "Inventory debug level"); + _screenWidth = 0; _screenHeight = 0; _screenSize = 0; _gameType = 0; @@ -86,6 +87,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam _inventory = 0; _currentLocationIndex = 0; _numLocations = 0; + _language = 0; } Parallaction::~Parallaction() { @@ -208,7 +210,7 @@ void Parallaction::allocateLocationSlot(const char *name) { error("No more location slots available. Please report this immediately to ScummVM team"); if (_currentLocationIndex == -1) { - strcpy(_locationNames[_numLocations], name); + Common::strlcpy(_locationNames[_numLocations], name, 10); _currentLocationIndex = _numLocations; _numLocations++; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 1e1c0b0a3d..9f045cb397 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -320,7 +320,7 @@ void Parallaction_br::changeLocation() { freeLocation(false); // load new location - strcpy(_location._name, _newLocationName.c_str()); + Common::strlcpy(_location._name, _newLocationName.c_str(), 100); parseLocation(_location._name); if (_location._startPosition.x != -1000) { diff --git a/engines/saga/isomap.cpp b/engines/saga/isomap.cpp index 77680178c1..e50378b9c0 100644 --- a/engines/saga/isomap.cpp +++ b/engines/saga/isomap.cpp @@ -97,6 +97,23 @@ IsoMap::IsoMap(SagaEngine *vm) : _vm(vm) { _viewScroll.x = (128 - 8) * 16; _viewScroll.y = (128 - 8) * 16 - 64; _viewDiff = 1; + _platformHeight = 0; + _queueCount = _readCount = 0; + + for (int i = 0; i < SAGA_DRAGON_SEARCH_DIAMETER; i++) + for (int j = 0; j < SAGA_DRAGON_SEARCH_DIAMETER; j++) + _dragonSearchArray.cell[i][j].visited = _dragonSearchArray.cell[i][j].direction = 0; + + for (int i = 0; i < SAGA_SEARCH_DIAMETER; i++) + for (int j = 0; j < SAGA_SEARCH_DIAMETER; j++) + _searchArray.cell[i][j].visited = _searchArray.cell[i][j].direction = 0; + + for (int i = 0; i < SAGA_SEARCH_QUEUE_SIZE; i++) { + memset(&_dragonSearchArray.queue[i], 0, sizeof(DragonTilePoint)); + memset(&_searchArray.queue[i], 0, sizeof(TilePoint)); + } + + memset(&_tileMap, 0, sizeof(TileMapData)); } void IsoMap::loadImages(const ByteArray &resourceData) { diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp index 099bf79e6b..2c9a02beec 100644 --- a/engines/saga/puzzle.cpp +++ b/engines/saga/puzzle.cpp @@ -86,6 +86,11 @@ Puzzle::Puzzle(SagaEngine *vm) : _vm(vm), _solved(false), _active(false) { _hintBox.setWidth(240); _hintBox.setHeight(30); + _hintNextRqState = kRQNoHint; + _hintGiver = 0; + _hintSpeaker = 0; + _slidePointX = _slidePointY = 0; + initPieceInfo( 0, 268, 18, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 3, Point(0, 1), Point(0, 62), Point(15, 31), Point(0, 0), Point(0, 0), Point(0,0)); initPieceInfo( 1, 270, 52, 0, 0, 0 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4, diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp index e659e09ce8..2d798bb0d6 100644 --- a/engines/saga/saveload.cpp +++ b/engines/saga/saveload.cpp @@ -56,7 +56,7 @@ SaveFileData *SagaEngine::getSaveFile(uint idx) { return &_saveFiles[_saveFilesCount - idx - 1]; } else { if (!emptySlot.name[0]) - strcpy(emptySlot.name, getTextString(kTextNewSave)); + Common::strlcpy(emptySlot.name, getTextString(kTextNewSave), SAVE_TITLE_SIZE); return (idx == 0) ? &emptySlot : &_saveFiles[_saveFilesCount - idx]; } diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 5f087ebd1a..c01613268a 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -349,6 +349,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Conquests of Camelot - English Atari ST + // Game version 1.019.000 + // Floppy: INT#10.12.90 + // Executable reports "1.002.038" + {"camelot", "", { + {"resource.map", 0, "0f80a11867be91a158823887a49cf443", 7290}, + {"resource.001", 0, "162f66c42e4146ee63f78fba6f1a6757", 596773}, + {"resource.002", 0, "162f66c42e4146ee63f78fba6f1a6757", 724615}, + {"resource.003", 0, "162f66c42e4146ee63f78fba6f1a6757", 713351}, + {"resource.004", 0, "162f66c42e4146ee63f78fba6f1a6757", 718766}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Conquests of Camelot - English DOS // SCI interpreter version 0.000.685 {"camelot", "", { @@ -939,6 +952,22 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 1 - English Atari ST + // Game version 1.000.104, SCI interpreter version 1.002.024 + {"hoyle1", "", { + {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518127}, + {"resource.map", 0, "0af9a3dcd72a091960de070432e1f524", 4386}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + + // Hoyle 1 - English Atari ST + // Game version 1.000.108, SCI interpreter version 1.002.026 + {"hoyle1", "", { + {"resource.map", 0, "ed8355f84752e49ffa1f0cf9eca4b28e", 4140}, + {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 517454}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 2 - English DOS // SCI interpreter version 0.000.572 {"hoyle2", "", { @@ -982,6 +1011,15 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 2 - English Atari ST + // Game version 1.001.017 + // Executable scanning reports "1.002.034" + {"hoyle2", "", { + {"resource.map", 0, "13c8cc977598b6ad61d24c6296a090fd", 1356}, + {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 216280}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 2 - English Macintosh // Executable scanning reports "x.yyy.zzz" {"hoyle2", "", { @@ -1977,6 +2015,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 2 - English Atari ST + // Game version 1.001.006 + // Executable reports "1.000.159" 1988-12-02 12:22 p.m. + {"lsl2", "", { + {"resource.map", 0, "2fc3ce7da1346e4dadfee18606d814fc", 4758}, + {"resource.001", 0, "4a24443a25e2b1492462a52809605dc2", 477342}, + {"resource.002", 0, "4a24443a25e2b1492462a52809605dc2", 406698}, + {"resource.003", 0, "4a24443a25e2b1492462a52809605dc2", 592433}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 2 - English DOS Non-Interactive Demo // Executable scanning reports "x.yyy.zzz" // SCI interpreter version 0.000.409 @@ -2034,6 +2083,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 2 - English Atari ST (Kixx) + // Game version 1.002.000 + // Executable reports "1.001.008" 1989-01-12 16:30 + {"lsl2", "", { + {"resource.map", 0, "2c9c3b0923e3764f5ab999bcb71c2d47", 4758}, + {"resource.001", 0, "4a24443a25e2b1492462a52809605dc2", 477625}, + {"resource.002", 0, "4a24443a25e2b1492462a52809605dc2", 406935}, + {"resource.003", 0, "4a24443a25e2b1492462a52809605dc2", 592533}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.032" // SCI interpreter version 0.000.685 @@ -2048,6 +2108,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - English Atari ST + // Game version 1.021, 1990-01-27 + // Int#6.26.90 + // Executable scanning reports "1.002.026" + {"lsl3", "", { + {"resource.map", 0, "0b6bd3e039682830a51c5755c06591db", 5916}, + {"resource.001", 0, "f18441027154292836b973c655fa3175", 456722}, + {"resource.002", 0, "f18441027154292836b973c655fa3175", 578024}, + {"resource.003", 0, "f18441027154292836b973c655fa3175", 506807}, + {"resource.004", 0, "f18441027154292836b973c655fa3175", 513651}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - English DOS (supplied by ssburnout in bug report #3049193) // 1.021 8x5.25" (label: Int#5.15.90) {"lsl3", "", { @@ -2916,6 +2989,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - English Atari ST + // Game version 1.002.011 DS 1989-07-21 + // Executable reports "1.002.003" + {"pq2", "", { + {"resource.map", 0, "28a6f471c7900c2c92da40eecb615d9d", 4584}, + {"resource.001", 0, "77f02def3094af804fd2371db25b7100", 509525}, + {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000}, + {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - English DOS (from FRG) // SCI interpreter version 0.000.395 {"pq2", "", { @@ -2935,6 +3019,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - English Atari ST + // Game version 1.001.006 1989-01-16 13:30 + // Executable reports "1.001.009" + {"pq2", "", { + {"resource.map", 0, "8e1161c684b342742d30f938a4839a4b", 4518}, + {"resource.001", 0, "77f02def3094af804fd2371db25b7100", 506563}, + {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 541261}, + {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 587511}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - Japanese PC-98 (also includes english language) // Executable scanning reports "x.yyy.zzz" // SCI interpreter version unknown @@ -3204,6 +3299,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 1 / Hero's Quest - English Atari ST + // Game version 1.137 + // Executable reports "1.002.028" + {"qfg1", "", { + {"resource.map", 0, "2a794066ad161acbedac8fa14e46905d", 6438}, + {"resource.000", 0, "40332d3ebfc70a4b6a6a0443c2763287", 79204}, + {"resource.001", 0, "f7fc269d3db146830d6427d3e02d4187", 473547}, + {"resource.002", 0, "e64004e020fdf1813be52b639b08be89", 635687}, + {"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640438}, + {"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644452}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 1 / Hero's Quest - English DOS Demo // Executable scanning reports "0.000.685" {"qfg1", "Demo", { @@ -3283,6 +3391,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English Amiga + // Game version 1.109 // Executable scanning reports "1.003.004" // SCI interpreter version 0.001.010 {"qfg2", "", { @@ -3705,6 +3814,18 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 3 - English Atari ST + // Game version 1.0Q 1989-27-03 17:00 + // Int#1.002.002 + // Executable reports "1.002.001" + {"sq3", "", { + {"resource.map", 0, "c36e322805949affd882a75803a6a54e", 5484}, + {"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 485146}, + {"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720227}, + {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688524}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 3 - German Amiga (also includes english language) // Executable scanning reports "1.004.006" // SCI interpreter version 0.000.453 (just a guess) diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 0867b20fc3..4c9d1221aa 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -186,6 +186,11 @@ Common::String ScummEngine_v70he::generateFilename(const int room) const { } if (_filenamePattern.genMethod == kGenHEPC || _filenamePattern.genMethod == kGenHEIOS) { + if (id == '3' && _game.id == GID_MOONBASE) { + result = Common::String::format("%s.u32", _filenamePattern.pattern); + break; + } + // For HE >= 98, we already called snprintf above. if (_game.heversion < 98 || room < 0) result = Common::String::format("%s.he%c", _filenamePattern.pattern, id); diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 5a994cb699..bb3e7f6ec3 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -245,9 +245,11 @@ static const GameSettings gameVariantsTable[] = { {"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, {"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_TOWNS, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO4(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_MIDITOWNS, GUIO_NOASPECT)}, {"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, + {"monkey", "SE Talkie", 0, GID_MONKEY, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_AUDIOTRACKS, UNK, GUIO0()}, {"monkey2", "", 0, GID_MONKEY2, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO1(GUIO_NOSPEECH)}, {"monkey2", "FM-TOWNS", 0, GID_MONKEY2, 5, 0, MDT_PCSPK | MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO5(GUIO_NOSPEECH, GUIO_MIDITOWNS, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_NOASPECT)}, + {"monkey2", "SE Talkie",0, GID_MONKEY2, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()}, {"atlantis", "", 0, GID_INDY4, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()}, {"atlantis", "Steam", "steam", GID_INDY4, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()}, diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h index 370f54c1d8..df62c59dd8 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -184,8 +184,11 @@ protected: }; #ifdef ENABLE_HE +class Moonbase; + class ScummEngine_v71he : public ScummEngine_v70he { friend class Wiz; + friend class Moonbase; protected: bool _skipProcessActors; @@ -244,6 +247,10 @@ public: void queueAuxEntry(int actorNum, int subIndex); void remapHEPalette(const uint8 *src, uint8 *dst); + +public: + /* Moonbase stuff */ + Moonbase *_moonbase; }; class ScummEngine_v72he : public ScummEngine_v71he { diff --git a/engines/scumm/he/logic/moonbase.cpp b/engines/scumm/he/logic/moonbase_logic.cpp index 3fcf30d6b5..a32356614f 100644 --- a/engines/scumm/he/logic/moonbase.cpp +++ b/engines/scumm/he/logic/moonbase_logic.cpp @@ -22,6 +22,7 @@ #include "scumm/he/intern_he.h" #include "scumm/he/logic_he.h" +#include "scumm/he/moonbase/moonbase.h" namespace Scumm { @@ -42,9 +43,10 @@ private: void op_load_multi_channel_wiz(int op, int numArgs, int32 *args); void op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *args); void op_dos_command(int op, int numArgs, int32 *args); - void op_set_fow_sentinel(int op, int numArgs, int32 *args); + void op_set_fow_sentinel(int32 *args); void op_set_fow_information(int op, int numArgs, int32 *args); - void op_set_fow_image(int op, int numArgs, int32 *args); + int op_set_fow_image(int op, int numArgs, int32 *args); + void op_ai_test_kludge(int op, int numArgs, int32 *args); void op_ai_master_control_program(int op, int numArgs, int32 *args); void op_ai_reset(int op, int numArgs, int32 *args); @@ -75,6 +77,44 @@ int LogicHEmoonbase::versionID() { #define OP_AI_SET_TYPE 10003 #define OP_AI_CLEAN_UP 10004 +#define OP_NET_REMOTE_START_SCRIPT 1492 +#define OP_NET_DO_INIT_ALL 1493 +#define OP_NET_DO_INIT_PROVIDER 1494 +#define OP_NET_DO_INIT_SESSION 1495 +#define OP_NET_DO_INIT_USER 1496 +#define OP_NET_QUERY_PROVIDERS 1497 +#define OP_NET_GET_PROVIDER_NAME 1498 +#define OP_NET_SET_PROVIDER 1499 +#define OP_NET_CLOSE_PROVIDER 1500 +#define OP_NET_QUERY_SESSIONS 1501 +#define OP_NET_GET_SESSION_NAME 1502 +#define OP_NET_CREATE_SESSION 1503 +#define OP_NET_JOIN_SESSION 1504 +#define OP_NET_END_SESSION 1505 +#define OP_NET_ADD_USER 1506 +#define OP_NET_REMOVE_USER 1507 +#define OP_NET_WHO_SENT_THIS 1508 +#define OP_NET_REMOTE_SEND_ARRAY 1509 +#define OP_NET_WHO_AM_I 1510 +#define OP_NET_REMOTE_START_FUNCTION 1511 +#define OP_NET_GET_PLAYER_LONG_NAME 1512 +#define OP_NET_GET_PLAYER_SHORT_NAME 1513 +#define OP_NET_SET_PROVIDER_BY_NAME 1516 +#define OP_NET_HOST_TCPIP_GAME 1517 +#define OP_NET_JOIN_TCPIP_GAME 1518 +#define OP_NET_SET_FAKE_LAG 1555 +#define OP_NET_GET_HOST_NAME 1556 +#define OP_NET_GET_IP_FROM_NAME 1557 +#define OP_NET_GET_SESSION_PLAYER_COUNT 1558 +#define OP_NET_DISABLE_SESSION_PLAYER_JOIN 1559 +#define OP_NET_START_QUERY_SESSIONS 1560 +#define OP_NET_UPDATE_QUERY_SESSIONS 1561 +#define OP_NET_STOP_QUERY_SESSIONS 1562 +#define OP_NET_DESTROY_PLAYER 1563 +#define OP_NET_ENABLE_SESSION_PLAYER_JOIN 1564 +#define OP_NET_SET_AI_PLAYER_COUNT 1565 + + int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) { switch (op) { case OP_CREATE_MULTI_STATE_WIZ: @@ -90,13 +130,13 @@ int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) { op_dos_command(op, numArgs, args); break; case OP_SET_FOW_SENTINEL: - op_set_fow_sentinel(op, numArgs, args); + op_set_fow_sentinel(args); break; case OP_SET_FOW_INFORMATION: op_set_fow_information(op, numArgs, args); break; case OP_SET_FOW_IMAGE: - op_set_fow_image(op, numArgs, args); + return op_set_fow_image(op, numArgs, args); break; case OP_AI_TEST_KLUDGE: @@ -142,19 +182,43 @@ void LogicHEmoonbase::op_dos_command(int op, int numArgs, int32 *args) { LogicHE::dispatch(op, numArgs, args); } -void LogicHEmoonbase::op_set_fow_sentinel(int op, int numArgs, int32 *args) { - warning("STUB: op_set_fow_sentinel()"); - LogicHE::dispatch(op, numArgs, args); +void LogicHEmoonbase::op_set_fow_sentinel(int32 *args) { + debug(2, "op_set_fow_sentinel(%d, %d, %d)", args[0], args[1], args[2]); + + _vm->_moonbase->_fowSentinelImage = args[0]; + _vm->_moonbase->_fowSentinelState = args[1]; + _vm->_moonbase->_fowSentinelConditionBits = args[2]; } void LogicHEmoonbase::op_set_fow_information(int op, int numArgs, int32 *args) { - warning("STUB: op_set_fow_information()"); - LogicHE::dispatch(op, numArgs, args); + Common::String str; + + str = Common::String::format("op_set_fow_information(%d", args[0]); + for (int i = 1; i < numArgs; i++) { + str += Common::String::format(", %d", args[i]); + } + str += ")"; + + debug(2, "%s", str.c_str()); + + _vm->_moonbase->setFOWInfo( + args[0], // array + args[1], // array down dimension + args[2], // array across dimension + args[3], // logical view X coordinate + args[4], // logical view Y coordinate + args[5], // screen draw clip rect x1 + args[6], // screen draw clip rect y1 + args[7], // screen draw clip rect x2 + args[8], // screen draw clip rect y2 + args[9], // techinque + args[10] // frame + ); } -void LogicHEmoonbase::op_set_fow_image(int op, int numArgs, int32 *args) { - warning("STUB: op_set_fow_image()"); - LogicHE::dispatch(op, numArgs, args); +int LogicHEmoonbase::op_set_fow_image(int op, int numArgs, int32 *args) { + debug(2, "op_set_fow_image(%d)", args[0]); + return _vm->_moonbase->setFOWImage(args[0]) ? 1 : 0; } void LogicHEmoonbase::op_ai_test_kludge(int op, int numArgs, int32 *args) { diff --git a/engines/scumm/he/moonbase/moonbase.cpp b/engines/scumm/he/moonbase/moonbase.cpp new file mode 100644 index 0000000000..34d4368725 --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.cpp @@ -0,0 +1,179 @@ +/* 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 "scumm/he/intern_he.h" +#include "scumm/he/moonbase/moonbase.h" + +namespace Scumm { + +Moonbase::Moonbase(ScummEngine_v71he *vm) : _vm(vm) { + initFOW(); +} + +Moonbase::~Moonbase() { +} + +void Moonbase::blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox, + uint8 *wizd, int x, int y, int rawROP, int paramROP) { + bool premulAlpa = false; + + if (rawROP == 1) + premulAlpa = true; + + Common::Rect clippedDstRect(dstw, dsth); + if (clipBox) { + Common::Rect clip(clipBox->left, clipBox->top, clipBox->right, clipBox->bottom); + if (clippedDstRect.intersects(clip)) { + clippedDstRect.clip(clip); + } else { + return; + } + } + + int width = READ_LE_UINT16(wizd + 0x8 + 0); + int height = READ_LE_UINT16(wizd + 0x8 + 2); + + Common::Rect srcLimitsRect(width, height); + Common::Rect dstOperation(x, y, x + width, y + height); + if (!clippedDstRect.intersects(dstOperation)) + return; + Common::Rect clippedRect = clippedDstRect.findIntersectingRect(dstOperation); + + int cx = clippedRect.right - clippedRect.left; + int cy = clippedRect.bottom - clippedRect.top; + + int sx = ((clippedRect.left - x) + srcLimitsRect.left); + int sy = ((clippedRect.top - y) + srcLimitsRect.top); + + dst += clippedRect.top * dstPitch + clippedRect.left * 2; + + int headerSize = READ_LE_UINT32(wizd + 0x4); + uint8 *dataPointer = wizd + 0x8 + headerSize; + + for (int i = 0; i < sy; i++) { + uint16 lineSize = READ_LE_UINT16(dataPointer + 0); + + dataPointer += lineSize; + } + + for (int i = 0; i < cy; i++) { + uint16 lineSize = READ_LE_UINT16(dataPointer + 0); + uint8 *singlesOffset = READ_LE_UINT16(dataPointer + 2) + dataPointer; + uint8 *quadsOffset = READ_LE_UINT16(dataPointer + 4) + dataPointer; + + int pixels = 0; + byte *dst1 = dst; + byte *codes = dataPointer + 6; + + while (1) { + int code = *codes - 2; + codes++; + + if (code <= 0) { // quad or single + uint8 *src; + int cnt; + if (code == 0) { // quad + src = quadsOffset; + quadsOffset += 8; + cnt = 4; // 4 pixels + } else { // single + src = singlesOffset; + singlesOffset += 2; + cnt = 1; + } + + for (int c = 0; c < cnt; c++) { + if (pixels >= sx) { + if (rawROP == 1) { // MMX_PREMUL_ALPHA_COPY + WRITE_LE_UINT16(dst1, READ_LE_UINT16(src)); + } else if (rawROP == 2) { // MMX_ADDITIVE + uint16 color = READ_LE_UINT16(src); + uint16 orig = READ_LE_UINT16(dst1); + + uint32 r = MIN<uint32>(0x7c00, (orig & 0x7c00) + (color & 0x7c00)); + uint32 g = MIN<uint32>(0x03e0, (orig & 0x03e0) + (color & 0x03e0)); + uint32 b = MIN<uint32>(0x001f, (orig & 0x001f) + (color & 0x001f)); + WRITE_LE_UINT16(dst1, (r | g | b)); + } else if (rawROP == 5) { // MMX_CHEAP_50_50 + uint16 color = (READ_LE_UINT16(src) >> 1) & 0x3DEF; + uint16 orig = (READ_LE_UINT16(dst1) >> 1) & 0x3DEF; + WRITE_LE_UINT16(dst1, (color + orig)); + } + dst1 += 2; + } + src += 2; + pixels++; + } + } else { // skip + if ((code & 1) == 0) { + code >>= 1; + + for (int j = 0; j < code; j++) { + if (pixels >= sx) + dst1 += 2; + pixels++; + } + } else { // special case + if (pixels >= sx) { + int alpha = code >> 1; + uint16 color = READ_LE_UINT16(singlesOffset); + uint32 orig = READ_LE_UINT16(dst1); + + if (!premulAlpa) { + WRITE_LE_UINT16(dst1, color); // ENABLE_PREMUL_ALPHA = 0 + } else { + if (alpha > 32) { + alpha -= 32; + + uint32 oR = orig & 0x7c00; + uint32 oG = orig & 0x03e0; + uint32 oB = orig & 0x1f; + uint32 dR = ((((color & 0x7c00) - oR) * alpha) >> 5) + oR; + uint32 dG = ((((color & 0x3e0) - oG) * alpha) >> 5) + oG; + uint32 dB = ((((color & 0x1f) - oB) * alpha) >> 5) + oB; + + WRITE_LE_UINT16(dst1, (dR & 0x7c00) | (dG & 0x3e0) | (dB & 0x1f)); + } else { + uint32 pix = ((orig << 16) | orig) & 0x3e07c1f; + pix = (((pix * alpha) & 0xffffffff) >> 5) & 0x3e07c1f; + pix = ((pix >> 16) + pix + color) & 0xffff; + WRITE_LE_UINT16(dst1, pix); + } + } + + dst1 += 2; + } + singlesOffset += 2; + pixels++; + } + } + + if (pixels >= cx + sx) + break; + } + + dataPointer += lineSize; + dst += dstPitch; + } +} + +} // End of namespace Scumm diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h new file mode 100644 index 0000000000..e82ae0164f --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.h @@ -0,0 +1,99 @@ +/* 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. + * + */ + +#ifndef SCUMM_HE_MOONBASE_H +#define SCUMM_HE_MOONBASE_H + +#ifdef ENABLE_HE + +#include "common/winexe_pe.h" + +namespace Scumm { + +class Moonbase { +public: + Moonbase(ScummEngine_v71he *vm); + ~Moonbase(); + + void blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox, + uint8 *wizd, int srcx, int srcy, int rawROP, int paramROP); + + // FOW Stuff + void initFOW(); + void releaseFOWResources(); + + bool setFOWImage(int id); + + void setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1, + int clipY1, int clipX2, int clipY2, int technique, int nFrame); + + + void renderFOW(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int flags); + +private: + int readFOWVisibilityArray(int array, int y, int x); + void renderFOWState(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int x, int y, int srcw, int srch, int state, int flags); + +public: + int _fowSentinelImage; + int _fowSentinelState; + uint32 _fowSentinelConditionBits; + +private: + ScummEngine_v71he *_vm; + + int _fowFrameBaseNumber; + int _fowAnimationFrames; + int _fowCurrentFOWFrame; + + int32 _fowTileW; + int32 _fowTileH; + + uint8 *_fowImage; + int _fowClipX1; + int _fowClipY1; + int _fowClipX2; + int _fowClipY2; + + int _fowDrawX; + int _fowDrawY; + + int _fowVtx1; + int _fowVty1; + int _fowMvx; + int _fowMvy; + int _fowVw; + int _fowVh; + + bool _fowBlackMode; + + int _fowRenderTable[32768]; + + Common::PEResources _exe; + Common::String _fileName; +}; + +} // End of namespace Scumm + +#endif // ENABLE_HE + +#endif // SCUMM_HE_MOONBASE_H diff --git a/engines/scumm/he/moonbase/moonbase_fow.cpp b/engines/scumm/he/moonbase/moonbase_fow.cpp new file mode 100644 index 0000000000..8be83a57f0 --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase_fow.cpp @@ -0,0 +1,410 @@ +/* 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/config-manager.h" + +#include "scumm/he/intern_he.h" +#include "scumm/he/moonbase/moonbase.h" + +namespace Scumm { + +#define FOW_ANIM_FRAME_COUNT 38 + +void Moonbase::initFOW() { + _fowSentinelImage = -1; + _fowSentinelState = -1; + _fowSentinelConditionBits = 0; + + _fowFrameBaseNumber = 0; + _fowAnimationFrames = 1; + _fowCurrentFOWFrame = 0; + + _fowTileW = 0; + _fowTileH = 0; + + _fowImage = nullptr; + _fowClipX1 = 0; + _fowClipY1 = 0; + _fowClipX2 = 0; + _fowClipY2 = 0; + + _fowDrawX = 0; + _fowDrawY = 0; + + _fowVtx1 = 0; + _fowVty1 = 0; + _fowMvx = 0; + _fowMvy = 0; + _fowVw = 0; + _fowVh = 0; + + _fowBlackMode = true; + + memset(_fowRenderTable, 0, 32768); +} + +void Moonbase::releaseFOWResources() { + if (_fowImage) { + free(_fowImage); + _fowImage = 0; + } +} + +bool Moonbase::setFOWImage(int image) { + releaseFOWResources(); + + if (!_fowImage) { + Common::String fowImageFilename(ConfMan.get("MOONX_FOWImageFilename").c_str()); + +#if 0 // TODO + if (!fowImageFilename.empty()) { + void *wiz = loadWizFromFilename(fowImageFilename); + + if (wiz) { + captureFOWImageFromLocation(wiz, file.size()); + free(wiz); + } + } +#endif + + if (!_fowImage && image < 0) { + int resId; + + // PIECES BUBBLES CIRCLES SIMPLE* WEDGEY BUBBLE2 + // WEDGE2 SPIKEY ANGLES SMOOTHED WUZZY SYS7-BEVELED + if (image >= -12 && image <= -1) + resId = 210 - image; // 211-222 range + else + resId = 214; // default, SIMPLE + + if (_fileName.empty()) { // We are running for the first time + _fileName = _vm->generateFilename(-3); + + if (!_exe.loadFromEXE(_fileName)) + error("Cannot open file %s", _fileName.c_str()); + } + + Common::SeekableReadStream *stream = _exe.getResource(Common::kPERCData, resId); + + if (stream->size()) { + _fowImage = (uint8 *)malloc(stream->size()); + + stream->read(_fowImage, stream->size()); + } + + delete stream; + } + + if (!_fowImage && image > 0) + _fowImage = _vm->getResourceAddress(rtImage, image); + + if (!_fowImage) + return false; + } + + int nStates = _vm->_wiz->getWizImageStates(_fowImage); + + if (nStates > FOW_ANIM_FRAME_COUNT) { + releaseFOWResources(); + return false; + } + + _fowAnimationFrames = (nStates + FOW_ANIM_FRAME_COUNT - 1) / FOW_ANIM_FRAME_COUNT; + + _vm->_wiz->getWizImageDim(_fowImage, (nStates - 1), _fowTileW, _fowTileH); + _fowBlackMode = !_vm->_wiz->isWizPixelNonTransparent(_fowImage, nStates - 1, 0, 0, 0); + + if (ConfMan.hasKey("EnableFOWRects")) + _fowBlackMode = (ConfMan.getInt("EnableFOWRects") == 1); + + return true; +} + +enum FOWElement { + FOW_EMPTY = 0, + FOW_SOLID = 1, + + FF_L = 0x01, + FF_R = 0x02, + FF_T = 0x04, + FF_B = 0x08, + FF_T_L = 0x10, + FF_T_R = 0x20, + FF_B_L = 0x40, + FF_B_R = 0x80, + FF_Q_A = (FF_L | FF_T | FF_T_L), + FF_Q_B = (FF_R | FF_T | FF_T_R), + FF_Q_C = (FF_L | FF_B | FF_B_L), + FF_Q_D = (FF_R | FF_B | FF_B_R) +}; + +int Moonbase::readFOWVisibilityArray(int array, int y, int x) { + _vm->VAR(116) = array; + + if (_vm->readArray(116, y, x) > 0) + return FOW_EMPTY; + + return FOW_SOLID; +} + +void Moonbase::setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1, + int clipY1, int clipX2, int clipY2, int technique, int nFrame) { + if (!_fowImage) + return; + + _fowDrawX = clipX1; + _fowDrawY = clipY1; + + _fowClipX1 = clipX1; + _fowClipY1 = clipY1; + _fowClipX2 = clipX2; + _fowClipY2 = clipY2; + + // Figure out the number of tiles are involved + int view_W = (clipX2 - clipX1) + 1; + int view_H = (clipY2 - clipY1) + 1; + + int tw = _fowTileW; + int th = _fowTileH; + + int dw = acrossDim; + int dh = downDim; + + int dlw = dw * tw; + int dlh = dh * th; + + _fowMvx = (0 <= viewX) ? (viewX % dlw) : (dlw - (-viewX % dlw)); + _fowMvy = (0 <= viewY) ? (viewY % dlh) : (dlh - (-viewY % dlh)); + + _fowVtx1 = _fowMvx / tw; + _fowVty1 = _fowMvy / th; + + _fowVw = (((_fowMvx + view_W + tw - 1) / tw) - _fowVtx1) + 1; + _fowVh = (((_fowMvy + view_H + th - 1) / th) - _fowVty1) + 1; + + // Build the connectivity table + int t = (_fowVty1 - 1); if (t >= dh) { t = 0; } else if (t < 0) { t = (dh - 1); } + int m = (_fowVty1 + 0); if (m >= dh) { m = 0; } else if (m < 0) { m = (dh - 1); } + int b = (_fowVty1 + 1); if (b >= dh) { b = 0; } else if (b < 0) { b = (dh - 1); } + + int il = (_fowVtx1 - 1); if (il >= dh) { il = 0; } else if (il < 0) { il = (dw - 1); } + int ic = (_fowVtx1 + 0); if (ic >= dh) { ic = 0; } else if (ic < 0) { ic = (dw - 1); } + int ir = (_fowVtx1 + 1); if (ir >= dh) { ir = 0; } else if (ir < 0) { ir = (dw - 1); } + + int dataOffset = (_fowVw * 3); + int dataOffset2 = (dataOffset * 2); + int *pOutterRenderTableA = _fowRenderTable; + int *pOutterRenderTableB = pOutterRenderTableA + dataOffset; + + for (int ay = 0; ay < _fowVh; ay++) { + int l = il; + int c = ic; + int r = ir; + + int *pRenderTableA = pOutterRenderTableA; + int *pRenderTableB = pOutterRenderTableB; + + pOutterRenderTableA += dataOffset2; + pOutterRenderTableB += dataOffset2; + + for (int ax = 0; ax < _fowVw; ax++) { + int visibility = readFOWVisibilityArray(fowInfoArray, m, c); + + if (visibility == FOW_EMPTY) { + int bits = 0; + + if (readFOWVisibilityArray(fowInfoArray, t, l) != 0) bits |= FF_T_L; + if (readFOWVisibilityArray(fowInfoArray, t, c) != 0) bits |= FF_T; + if (readFOWVisibilityArray(fowInfoArray, t, r) != 0) bits |= FF_T_R; + if (readFOWVisibilityArray(fowInfoArray, m, l) != 0) bits |= FF_L; + if (readFOWVisibilityArray(fowInfoArray, m, r) != 0) bits |= FF_R; + if (readFOWVisibilityArray(fowInfoArray, b, l) != 0) bits |= FF_B_L; + if (readFOWVisibilityArray(fowInfoArray, b, c) != 0) bits |= FF_B; + if (readFOWVisibilityArray(fowInfoArray, b, r) != 0) bits |= FF_B_R; + + if (bits) { + *pRenderTableA++ = 1; + *pRenderTableB++ = 1; + + // Quadrant (A) + if (bits & FF_Q_A) { + *pRenderTableA++ = ( + ((FF_L & bits) ? 1 : 0) | + ((FF_T & bits) ? 2 : 0) | + ((FF_T_L & bits) ? 4 : 0) + ) + 0; + } else { + *pRenderTableA++ = 0; + } + + // Quadrant (B) + if (bits & FF_Q_B) { + *pRenderTableA++ = ( + ((FF_R & bits) ? 1 : 0) | + ((FF_T & bits) ? 2 : 0) | + ((FF_T_R & bits) ? 4 : 0) + ) + 8; + } else { + *pRenderTableA++ = 0; + } + + // Quadrant (C) + if (bits & FF_Q_C) { + *pRenderTableB++ = ( + ((FF_L & bits) ? 1 : 0) | + ((FF_B & bits) ? 2 : 0) | + ((FF_B_L & bits) ? 4 : 0) + ) + 16; + } else { + *pRenderTableB++ = 0; + } + + // Quadrant (D) + if (bits & FF_Q_D) { + *pRenderTableB++ = ( + ((FF_R & bits) ? 1 : 0) | + ((FF_B & bits) ? 2 : 0) | + ((FF_B_R & bits) ? 4 : 0) + ) + 24; + } else { + *pRenderTableB++ = 0; + } + } else { + *pRenderTableA++ = 0; + *pRenderTableB++ = 0; + } + } else { + if (_fowBlackMode) { + *pRenderTableA++ = 2; + *pRenderTableB++ = 2; + } else { + *pRenderTableA++ = 1; + *pRenderTableA++ = 33; + *pRenderTableA++ = 34; + + *pRenderTableB++ = 1; + *pRenderTableB++ = 35; + *pRenderTableB++ = 36; + } + } + + if (++l >= dw) { l = 0; } + if (++c >= dw) { c = 0; } + if (++r >= dw) { r = 0; } + } + + if (++t >= dh) { t = 0; } + if (++m >= dh) { m = 0; } + if (++b >= dh) { b = 0; } + } + + _fowCurrentFOWFrame = (nFrame >= 0) ? (nFrame % _fowAnimationFrames) : ((-nFrame) % _fowAnimationFrames); + _fowFrameBaseNumber = (_fowCurrentFOWFrame * FOW_ANIM_FRAME_COUNT); +} + +void Moonbase::renderFOWState(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int x, int y, int srcw, int srch, int state, int flags) { + int32 spotx, spoty; + + _vm->_wiz->getWizImageSpot(_fowImage, state, spotx, spoty); + Common::Rect r(_fowClipX1, _fowClipY1, _fowClipX2, _fowClipY2); + + _vm->_wiz->drawWizImageEx(destSurface, _fowImage, 0, dstPitch, dstType, dstw, dsth, x - spotx, y - spoty, srcw, srch, state, &r, flags, 0, 0, 16, 0, 0); +} + +static void blackRect_16bpp(uint8 *destSurface, int x1, int y1, int x2, int y2) { + // TODO +} + +void Moonbase::renderFOW(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int flags) { + if (!_fowImage) + return; + + const int *pOutterRenderTable = _fowRenderTable; + int ixPos = ((_fowVtx1 * _fowTileW) - _fowMvx) + _fowDrawX; + int yPos = ((_fowVty1 * _fowTileH) - _fowMvy) + _fowDrawY; + int dataOffset = _fowVw * 3; + int halfTileHeight = _fowTileH / 2; + int cx2 = MIN(_fowClipX2, (dstw - 1)); + int cy2 = MIN(_fowClipY2, (dsth - 1)); + + for (int ry = 0; ry < _fowVh; ry++) { + int real_yPos = yPos; + + for (int i = 0; i < 2; i++) { + const int *pRenderTable = pOutterRenderTable; + pOutterRenderTable += dataOffset; + + int xPos = ixPos; + + for (int rx = 0; rx < _fowVw; rx++) { + int nState = *pRenderTable++; + + if (nState != 0) { + if (nState == 2) { + int countLeft = (_fowVw - rx); + int count = 0; + + for (; count < countLeft; count++) { + if (*(pRenderTable + count) != 2) + break; + + pRenderTable++; + rx++; + } + count++; + + int x1 = xPos; + int y1 = real_yPos; + + xPos += _fowTileW * count; + int x2 = (xPos - 1); + int y2 = ((y1 + halfTileHeight) - 1); + + x1 = MAX(0, x1); + y1 = MAX(0, y1); + x2 = MIN(x2, cx2); + y2 = MIN(y2, cy2); + + if ((x2 >= x1) && (y2 >= y1) && (x1 <= _fowClipX2) && (y1 <= _fowClipY2)) + blackRect_16bpp(destSurface, x1, y1, x2, y2); + } else { + int subState; + + if ((subState = *pRenderTable++) != 0) + renderFOWState(destSurface, dstPitch, dstType, dstw, dsth, xPos, yPos, _fowTileW, _fowTileH, (subState + _fowFrameBaseNumber), flags); + + if ((subState = *pRenderTable++) != 0) + renderFOWState(destSurface, dstPitch, dstType, dstw, dsth, xPos, yPos, _fowTileW, _fowTileH, (subState + _fowFrameBaseNumber), flags); + + xPos += _fowTileW; + } + } else { + xPos += _fowTileW; + } + } + real_yPos += halfTileHeight; + } + yPos += _fowTileH; + } +} + +} // End of namespace Scumm diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp index e69308c067..7d56138247 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -1997,6 +1997,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { _sprite->setSpriteFlagRemapPalette(spriteId, args[0]); break; default: + warning("Unknown sprite property %d for sprite %d", args[0], spriteId); break; } break; diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp index 9a456b86c0..2e0a03af7f 100644 --- a/engines/scumm/he/sound_he.cpp +++ b/engines/scumm/he/sound_he.cpp @@ -470,6 +470,10 @@ void SoundHE::processSoundOpcodes(int sound, byte *codePtr, int *soundVars) { if (arg == 2) { val = getSoundVar(sound, val); } + if (!val) { + val = 1; // Safeguard for division by zero + warning("Incorrect value 0 for processSoundOpcodes() kludge DIV"); + } val = getSoundVar(sound, var) / val; setSoundVar(sound, var, val); break; diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp index 245a986531..b192fab233 100644 --- a/engines/scumm/he/sprite_he.cpp +++ b/engines/scumm/he/sprite_he.cpp @@ -386,7 +386,7 @@ int Sprite::getSpriteGeneralProperty(int spriteId, int type) { case 0x7B: return _spriteTable[spriteId].imgFlags; case 0x7D: - return _spriteTable[spriteId].field_90; + return _spriteTable[spriteId].conditionBits; case 0x7E: return _spriteTable[spriteId].animProgress; default: @@ -746,7 +746,7 @@ void Sprite::setSpriteField84(int spriteId, int value) { } void Sprite::setSpriteGeneralProperty(int spriteId, int type, int value) { - debug(0, "setSpriteGeneralProperty: spriteId %d type 0x%x", spriteId, type); + debug(0, "setSpriteGeneralProperty: spriteId %d type 0x%x value 0x%x", spriteId, type, value); assertRange(1, spriteId, _varNumSprites, "sprite"); int32 delay; @@ -758,7 +758,7 @@ void Sprite::setSpriteGeneralProperty(int spriteId, int type, int value) { _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw; break; case 0x7D: - _spriteTable[spriteId].field_90 = value; + _spriteTable[spriteId].conditionBits = value; _spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw; break; case 0x7E: @@ -799,7 +799,7 @@ void Sprite::resetSprite(int spriteId) { _spriteTable[spriteId].priority = 0; _spriteTable[spriteId].field_84 = 0; _spriteTable[spriteId].imgFlags = 0; - _spriteTable[spriteId].field_90 = 0; + _spriteTable[spriteId].conditionBits = 0; if (_vm->_game.heversion >= 100) { _spriteTable[spriteId].flags &= ~kSFMarkDirty; @@ -1292,7 +1292,7 @@ void Sprite::processImages(bool arg) { wiz.spriteId = spi->id; wiz.spriteGroup = spi->group; - wiz.field_23EA = spi->field_90; + wiz.conditionBits = spi->conditionBits; spi->curImageState = wiz.img.state = imageState; spi->curImage = wiz.img.resNum = image; wiz.processFlags = kWPFNewState | kWPFSetPos; @@ -1341,7 +1341,7 @@ void Sprite::processImages(bool arg) { wiz.img.flags |= kWIFRemapPalette; if (spi->field_84) { wiz.processFlags |= 0x200000; - wiz.img.field_390 = spi->field_84; + wiz.img.zbuffer = spi->field_84; wiz.img.zorder = spi->priority; } if (spi->sourceImage) { @@ -1426,7 +1426,7 @@ void Sprite::saveOrLoadSpriteData(Serializer *s) { MKLINE(SpriteInfo, field_84, sleInt32, VER(48)), MKLINE(SpriteInfo, classFlags, sleInt32, VER(48)), MKLINE(SpriteInfo, imgFlags, sleInt32, VER(48)), - MKLINE(SpriteInfo, field_90, sleInt32, VER(48)), + MKLINE(SpriteInfo, conditionBits, sleInt32, VER(48)), MKEND() }; diff --git a/engines/scumm/he/sprite_he.h b/engines/scumm/he/sprite_he.h index e31ccbf790..b1a7641fcc 100644 --- a/engines/scumm/he/sprite_he.h +++ b/engines/scumm/he/sprite_he.h @@ -79,7 +79,7 @@ struct SpriteInfo { int32 field_84; int32 classFlags; int32 imgFlags; - int32 field_90; + int32 conditionBits; }; struct SpriteGroup { diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp index 9a59609651..43994c33d6 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -31,6 +31,7 @@ #include "scumm/scumm.h" #include "scumm/util.h" #include "scumm/he/wiz_he.h" +#include "scumm/he/moonbase/moonbase.h" namespace Scumm { @@ -976,7 +977,7 @@ void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, int dstType, const uin } } -int Wiz::isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth) { +int Wiz::isPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth) { if (x < 0 || x >= w || y < 0 || y >= h) { return 0; } @@ -1422,19 +1423,19 @@ void Wiz::displayWizImage(WizImage *pwi) { wi->state = pwi->state; wi->flags = pwi->flags; wi->shadow = 0; - wi->field_390 = 0; + wi->zbuffer = 0; wi->palette = 0; ++_imagesNum; } else if (pwi->flags & kWIFIsPolygon) { drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, 0, 0, 0); } else { const Common::Rect *r = NULL; - drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0)); + drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0), 0); } } -uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr) { - debug(3, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d field_390 %d dstResNum %d)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, field_390, dstResNum); +uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int zbuffer, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr, uint32 conditionBits) { + debug(3, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d zbuffer %d dstResNum %d conditionBits: 0x%x)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, zbuffer, dstResNum, conditionBits); uint8 *dataPtr; uint8 *dst = NULL; @@ -1456,9 +1457,6 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int uint32 height = READ_LE_UINT32(wizh + 0x8); debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height); - uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); - assert(wizd); - uint8 *mask = NULL; if (maskNum) { uint8 *maskPtr = _vm->getResourceAddress(rtImage, maskNum); @@ -1574,58 +1572,261 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1; } + if (_vm->_game.id == GID_MOONBASE && + resNum == _vm->_moonbase->_fowSentinelImage && + state == _vm->_moonbase->_fowSentinelState && + conditionBits == _vm->_moonbase->_fowSentinelConditionBits) { + _vm->_moonbase->renderFOW(dst, dstPitch, dstType, cw, ch, flags); + x1 = 0; + y1 = 0; + width = rScreen.width(); + height = rScreen.height(); + } else { + drawWizImageEx(dst, dataPtr, mask, dstPitch, dstType, cw, ch, x1, y1, width, height, + state, &rScreen, flags, palPtr, transColor, _vm->_bytesPerPixel, xmapPtr, conditionBits); + } + + if (!(flags & kWIFBlitToMemBuffer) && dstResNum == 0) { + Common::Rect rImage(x1, y1, x1 + width, y1 + height); + if (rImage.intersects(rScreen)) { + rImage.clip(rScreen); + if (!(flags & kWIFBlitToFrontVideoBuffer) && (flags & (kWIFBlitToFrontVideoBuffer | kWIFMarkBufferDirty))) { + ++rImage.bottom; + _vm->markRectAsDirty(kMainVirtScreen, rImage); + } else { + _vm->restoreBackgroundHE(rImage); + } + } + } + + return dst; +} + +void Wiz::drawWizImageEx(uint8 *dst, uint8 *dataPtr, uint8 *maskPtr, int dstPitch, int dstType, + int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *rect, + int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits) { + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); + assert(wizh); + uint32 comp = READ_LE_UINT32(wizh + 0x0); + uint32 width = READ_LE_UINT32(wizh + 0x4); + uint32 height = READ_LE_UINT32(wizh + 0x8); + debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height); + + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); + assert(wizd); + switch (comp) { case 0: - copyRawWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor, _vm->_bytesPerPixel); + copyRawWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr, transColor, bitDepth); break; case 1: - if (flags & 0x80) { + if (flags & kWIFZPlaneOn) { dst = _vm->getMaskBuffer(0, 0, 1); dstPitch /= _vm->_bytesPerPixel; - copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 2); - } else if (flags & 0x100) { + copyWizImageWithMask(dst, wizd, dstPitch, dstw, dsth, srcx, srcy, srcw, srch, rect, 0, 2); + } else if (flags & kWIFZPlaneOff) { dst = _vm->getMaskBuffer(0, 0, 1); dstPitch /= _vm->_bytesPerPixel; - copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 1); + copyWizImageWithMask(dst, wizd, dstPitch, dstw, dsth, srcx, srcy, srcw, srch, rect, 0, 1); } else { - copyWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr, _vm->_bytesPerPixel); + copyWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr, xmapPtr, bitDepth); } break; #ifdef USE_RGB_COLOR case 2: - if (maskNum) { - copyMaskWizImage(dst, wizd, mask, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr); + if (maskPtr) { + copyMaskWizImage(dst, wizd, maskPtr, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr); } else { - copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, transColor); + copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, transColor); } break; case 4: - // TODO: Unknown image type + copyCompositeWizImage(dst, dataPtr, wizd, maskPtr, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, state, rect, flags, palPtr, transColor, bitDepth, xmapPtr, conditionBits); break; case 5: - copy16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, xmapPtr); + copy16BitWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, xmapPtr); + break; + case 9: + copy555WizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, rect, conditionBits); break; #endif default: - error("drawWizImage: Unhandled wiz compression type %d", comp); + error("drawWizImageEx: Unhandled wiz compression type %d", comp); } +} - if (!(flags & kWIFBlitToMemBuffer) && dstResNum == 0) { - Common::Rect rImage(x1, y1, x1 + width, y1 + height); - if (rImage.intersects(rScreen)) { - rImage.clip(rScreen); - if (!(flags & kWIFBlitToFrontVideoBuffer) && (flags & (kWIFBlitToFrontVideoBuffer | kWIFMarkBufferDirty))) { - ++rImage.bottom; - _vm->markRectAsDirty(kMainVirtScreen, rImage); - } else { - _vm->restoreBackgroundHE(rImage); +#ifdef USE_RGB_COLOR + +void Wiz::copyCompositeWizImage(uint8 *dst, uint8 *wizPtr, uint8 *compositeInfoBlockPtr, uint8 *maskPtr, int dstPitch, int dstType, + int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *clipBox, + int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits) { + + uint8 *nestedBlockHeader = _vm->heFindResource(MKTAG('N','E','S','T'), wizPtr); + assert(nestedBlockHeader); + + uint8 *nestedWizHeader = _vm->heFindResource(MKTAG('M','U','L','T'), nestedBlockHeader); + assert(nestedWizHeader); + + uint16 layerCount = READ_LE_UINT16(compositeInfoBlockPtr); + compositeInfoBlockPtr += 2; + + uint16 defaultSubConditionBits = (conditionBits & kWMSBReservedBits); + + conditionBits &= ~kWMSBReservedBits; + + for (uint layerCounter = 0; layerCounter < layerCount; layerCounter++) { + int cmdSize = READ_LE_UINT16(compositeInfoBlockPtr); + uint8 *cmdPtr = compositeInfoBlockPtr + 2; + + compositeInfoBlockPtr += (cmdSize + 2); + uint32 layerCmdDataBits = READ_LE_UINT32(cmdPtr); + cmdPtr += 4; + + uint32 subConditionBits; + + if (layerCmdDataBits & kWCFConditionBits) { + uint32 layerConditionBits = READ_LE_UINT32(cmdPtr); + cmdPtr += 4; + + subConditionBits = (layerConditionBits & kWMSBReservedBits); + layerConditionBits &= ~kWMSBReservedBits; + + if (subConditionBits == 0) + subConditionBits = defaultSubConditionBits; + + uint32 conditionType = (layerConditionBits & kWSPCCTBits); + layerConditionBits &= ~kWSPCCTBits; + + switch (conditionType) { + case kWSPCCTAnd: + if (layerConditionBits != (layerConditionBits & conditionBits)) + continue; + break; + + case kWSPCCTNot: + if (layerConditionBits & conditionBits) + continue; + break; + + case kWSPCCTOr: + default: + if (!(layerConditionBits & conditionBits)) + continue; + break; } + } else { + subConditionBits = defaultSubConditionBits; } + + uint16 subState; + if (layerCmdDataBits & kWCFSubState) { + subState = READ_LE_UINT16(cmdPtr); + cmdPtr += 2; + } else { + subState = 0; + } + + int16 xPos; + if (layerCmdDataBits & kWCFXDelta) { + xPos = (int16)READ_LE_UINT16(cmdPtr); + cmdPtr += 2; + } else { + xPos = 0; + } + + int16 yPos; + if (layerCmdDataBits & kWCFYDelta) { + yPos = (int16)READ_LE_UINT16(cmdPtr); + cmdPtr += 2; + } else { + yPos = 0; + } + + uint32 drawFlags; + if (layerCmdDataBits & kWCFDrawFlags) { + drawFlags = READ_LE_UINT32(cmdPtr); + cmdPtr += 4; + } else { + drawFlags = flags; + } + + uint srcw1, srch1; + if (drawFlags & (kWIFFlipX | kWIFFlipY)) { + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), wizPtr, subState, 0); + assert(wizh); + srcw1 = READ_LE_UINT32(wizh + 0x4); + srch1 = READ_LE_UINT32(wizh + 0x8); + } + + if (drawFlags & kWIFFlipX) + xPos = (srcw - (xPos + srcw1)); + + if (drawFlags & kWIFFlipY) + yPos = (srch - (yPos + srch1)); + + if (layerCmdDataBits & kWCFSubConditionBits) { + subConditionBits = READ_LE_UINT32(cmdPtr); + cmdPtr += 4; + } + + drawWizImageEx(dst, nestedWizHeader, maskPtr, dstPitch, dstType, dstw, dsth, srcx + xPos, srcy + yPos, srcw, srch, + subState, clipBox, drawFlags, palPtr, transColor, bitDepth, xmapPtr, subConditionBits); + } +} + +void Wiz::copy555WizImage(uint8 *dst, uint8 *wizd, int dstPitch, int dstType, + int dstw, int dsth, int srcx, int srcy, const Common::Rect *clipBox, uint32 conditionBits) { + + int rawROP = conditionBits & kWMSBRopMask; + int paramROP = (conditionBits & kWMSBReservedBits) >> kWMSBRopParamRShift; + + switch (rawROP) { + default: + case 1: + rawROP = 1; + // MMX_PREMUL_ALPHA_COPY + break; + + case 2: + //warning("T14: MMX_ADDITIVE"); + break; + + case 3: + warning("T14: MMX_SUBTRACTIVE"); + break; + + case 4: + warning("T14: MMX_CONSTANT_ALPHA"); + break; + + case 5: + //warning("T14: MMX_CHEAP_50_50"); + break; + + case 6: + warning("T14: COPY"); + break; + + case 7: + warning("T14: CHEAP_50_50"); + break; + } + + + uint32 compID = READ_LE_UINT32(wizd); + + if (compID == 0x12340102) { + _vm->_moonbase->blitT14WizImage(dst, dstw, dsth, dstPitch, clipBox, wizd, srcx, srcy, rawROP, paramROP); + } else if (compID == 0x12340802) { + warning("Distorion codec"); + } else if (compID == 0x12340902) { + error("Unsupported Distortion"); } - return dst; } +#endif + struct PolygonDrawData { struct PolygonArea { int32 xmin; @@ -1747,7 +1948,7 @@ void Wiz::captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int assert(maskNum); const Common::Rect *r = NULL; - const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0); + const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0, 0); getWizImageDim(maskNum, maskState, srcw, srch); dstw = wp->bound.width(); @@ -1815,7 +2016,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int debug(0, "drawWizPolygonTransform() unhandled flag 0x800000"); } - srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette)); + srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette), 0); } else { assert(_vm->_bytesPerPixel == 1); uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); @@ -1826,7 +2027,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int } } else { if (getWizImageData(resNum, state, 0) != 0) { - srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette)); + srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette), 0); } else { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); @@ -2001,7 +2202,7 @@ void Wiz::flushWizBuffer() { drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, pwi->shadow, 0, pwi->palette); } else { const Common::Rect *r = NULL; - drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->field_390, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette)); + drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->zbuffer, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette), 0); } } _imagesNum = 0; @@ -2023,7 +2224,7 @@ void Wiz::loadWizCursor(int resId, int palette) { const Common::Rect *r = NULL; _cursorImage = true; - uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette)); + uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette), 0); _cursorImage = false; int32 cw, ch; @@ -2073,10 +2274,10 @@ void Wiz::displayWizComplexImage(const WizParameters *params) { if (params->processFlags & kWPFShadow) { shadow = params->img.shadow; } - int field_390 = 0; - if (params->processFlags & 0x200000) { - field_390 = params->img.field_390; - debug(0, "displayWizComplexImage() unhandled flag 0x200000"); + int zbuffer = 0; + if (params->processFlags & kWPFZBuffer) { + zbuffer = params->img.zbuffer; + debug(0, "displayWizComplexImage() unhandled flag kWPFZBuffer"); } const Common::Rect *r = NULL; if (params->processFlags & kWPFClipBox) { @@ -2104,19 +2305,19 @@ void Wiz::displayWizComplexImage(const WizParameters *params) { pwi->state = state; pwi->flags = flags; pwi->shadow = shadow; - pwi->field_390 = field_390; + pwi->zbuffer = zbuffer; pwi->palette = palette; ++_imagesNum; } else { if (sourceImage != 0) { - drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette)); + drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), 0); } else if (params->processFlags & (kWPFScaled | kWPFRotate)) { drawWizComplexPolygon(params->img.resNum, state, po_x, po_y, shadow, rotationAngle, scale, r, flags, dstResNum, palette); } else { if (flags & kWIFIsPolygon) { drawWizPolygon(params->img.resNum, state, po_x, flags, shadow, dstResNum, palette); } else { - drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette)); + drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), params->conditionBits); } } } @@ -2501,6 +2702,10 @@ void Wiz::processWizImage(const WizParameters *params) { void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); + getWizImageDim(dataPtr, state, w, h); +} + +void Wiz::getWizImageDim(uint8 *dataPtr, int state, int32 &w, int32 &h) { uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); w = READ_LE_UINT32(wizh + 0x4); @@ -2510,6 +2715,10 @@ void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) { void Wiz::getWizImageSpot(int resId, int state, int32 &x, int32 &y) { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resId); assert(dataPtr); + getWizImageSpot(dataPtr, state, x, y); +} + +void Wiz::getWizImageSpot(uint8 *dataPtr, int state, int32 &x, int32 &y) { uint8 *spotPtr = _vm->findWrappedBlock(MKTAG('S','P','O','T'), dataPtr, state, 0); if (spotPtr) { x = READ_LE_UINT32(spotPtr + 0); @@ -2547,6 +2756,11 @@ int Wiz::getWizImageData(int resNum, int state, int type) { int Wiz::getWizImageStates(int resNum) { const uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); + + return getWizImageStates(dataPtr); +} + +int Wiz::getWizImageStates(const uint8 *dataPtr) { if (READ_BE_UINT32(dataPtr) == MKTAG('M','U','L','T')) { const byte *offs, *wrap; @@ -2565,9 +2779,14 @@ int Wiz::getWizImageStates(int resNum) { } int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags) { - int ret = 0; uint8 *data = _vm->getResourceAddress(rtImage, resNum); assert(data); + + return isWizPixelNonTransparent(data, state, x, y, flags); +} + +int Wiz::isWizPixelNonTransparent(uint8 *data, int state, int x, int y, int flags) { + int ret = 0; uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); @@ -2591,19 +2810,20 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags } break; case 1: - ret = isWizPixelNonTransparent(wizd, x, y, w, h, 1); + ret = isPixelNonTransparent(wizd, x, y, w, h, 1); break; #ifdef USE_RGB_COLOR case 2: ret = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)) != _vm->VAR(_vm->VAR_WIZ_TCOLOR) ? 1 : 0; break; - case 4: - // TODO: Unknown image type - ret = 1; - debug(0, "isWizPixelNonTransparent: Unhandled wiz compression type %d", c); + case 4: { + uint16 color = 0xffff; + copyCompositeWizImage((byte *)&color, data, wizd, 0, 2, kDstMemory, 1, 1, -x, -y, w, h, state, 0, 0, 0, 0, 2, 0, 0); + ret = color != 0xffff; break; + } case 5: - ret = isWizPixelNonTransparent(wizd, x, y, w, h, 2); + ret = isPixelNonTransparent(wizd, x, y, w, h, 2); break; #endif default: @@ -2641,8 +2861,7 @@ uint16 Wiz::getWizPixelColor(int resNum, int state, int x, int y) { color = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)); break; case 4: - // TODO: Unknown image type - debug(0, "getWizPixelColor: Unhandled wiz compression type %d", c); + copyCompositeWizImage((byte *)&color, data, wizd, 0, 2, kDstMemory, 1, 1, -x, -y, w, h, state, 0, 0, 0, 0, 2, 0, 0); break; case 5: color = getWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)); diff --git a/engines/scumm/he/wiz_he.h b/engines/scumm/he/wiz_he.h index 974b394d61..692ad76db5 100644 --- a/engines/scumm/he/wiz_he.h +++ b/engines/scumm/he/wiz_he.h @@ -43,7 +43,7 @@ struct WizImage { int state; int flags; int shadow; - int field_390; + int zbuffer; int palette; }; @@ -102,10 +102,10 @@ struct WizParameters { FontProperties fontProperties; EllipseProperties ellipseProperties; Common::Rect box2; - int field_23DE; + int blendFlags; int spriteId; int spriteGroup; - int field_23EA; + int conditionBits; WizImage img; }; @@ -117,6 +117,9 @@ enum WizImageFlags { kWIFMarkBufferDirty = 0x10, kWIFBlitToMemBuffer = 0x20, kWIFIsPolygon = 0x40, + kWIFZPlaneOn = 0x80, + kWIFZPlaneOff = 0x100, + kWIFUseShadow = 0x200, kWIFFlipX = 0x400, kWIFFlipY = 0x800 }; @@ -138,7 +141,31 @@ enum WizProcessFlags { kWPFFillColor = 0x20000, kWPFClipBox2 = 0x40000, kWPFMaskImg = 0x80000, - kWPFParams = 0x100000 + kWPFParams = 0x100000, + kWPFZBuffer = 0x200000 +}; + +enum WizCompositeFlags { + kWCFConditionBits = 0x01, + kWCFSubState = 0x02, + kWCFXDelta = 0x04, + kWCFYDelta = 0x08, + kWCFDrawFlags = 0x10, + kWCFSubConditionBits = 0x20 +}; + +enum WizSpcConditionTypes { + kWSPCCTBits = 0xc0000000, + kWSPCCTOr = 0x00000000, + kWSPCCTAnd = 0x40000000, + kWSPCCTNot = 0x80000000 +}; + +enum WizMoonSystemBits { + kWMSBRopMask = 0xff, + kWMSBRopParamMask = 0xff00, + kWMSBReservedBits = (kWMSBRopMask | kWMSBRopParamMask), + kWMSBRopParamRShift = 8 }; enum { @@ -193,14 +220,19 @@ public: void remapWizImagePal(const WizParameters *params); void getWizImageDim(int resNum, int state, int32 &w, int32 &h); + void getWizImageDim(uint8 *dataPtr, int state, int32 &w, int32 &h); int getWizImageStates(int resnum); + int getWizImageStates(const uint8 *ptr); int isWizPixelNonTransparent(int resnum, int state, int x, int y, int flags); + int isWizPixelNonTransparent(uint8 *data, int state, int x, int y, int flags); + int isPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth); uint16 getWizPixelColor(int resnum, int state, int x, int y); int getWizImageData(int resNum, int state, int type); void flushWizBuffer(); void getWizImageSpot(int resId, int state, int32 &x, int32 &y); + void getWizImageSpot(uint8 *data, int state, int32 &x, int32 &y); void loadWizCursor(int resId, int palette); void captureWizImage(int resNum, const Common::Rect& r, bool frontBuffer, int compType); @@ -210,7 +242,8 @@ public: void displayWizImage(WizImage *pwi); void processWizImage(const WizParameters *params); - uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr); + uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int zbuffer, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr, uint32 conditionBits); + void drawWizImageEx(uint8 *dst, uint8 *src, uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits); void drawWizPolygon(int resNum, int state, int id, int flags, int shadow, int dstResNum, int palette); void drawWizComplexPolygon(int resNum, int state, int po_x, int po_y, int shadow, int angle, int zoom, const Common::Rect *r, int flags, int dstResNum, int palette); void drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette); @@ -218,6 +251,12 @@ public: #ifdef USE_RGB_COLOR static void copyMaskWizImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr); + + void copyCompositeWizImage(uint8 *dst, uint8 *wizPtr, uint8 *wizd, uint8 *maskPtr, int dstPitch, int dstType, + int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *clipBox, + int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits); + void copy555WizImage(uint8 *dst, uint8 *wizd, int dstPitch, int dstType, + int dstw, int dsth, int srcx, int srcy, const Common::Rect *clipBox, uint32 conditionBits); #endif static void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, uint8 bitdepth); @@ -238,7 +277,6 @@ public: template<int type> static void write8BitColor(uint8 *dst, const uint8 *src, int dstType, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth); static void writeColor(uint8 *dstPtr, int dstType, uint16 color); - int isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth); uint16 getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color); uint16 getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color); void computeWizHistogram(uint32 *histogram, const uint8 *data, const Common::Rect& rCapt); diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index 416a8f7ef9..c56ef7e5f4 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -136,9 +136,11 @@ MODULE_OBJS += \ he/logic/basketball.o \ he/logic/football.o \ he/logic/funshop.o \ - he/logic/moonbase.o \ + he/logic/moonbase_logic.o \ he/logic/puttrace.o \ - he/logic/soccer.o + he/logic/soccer.o \ + he/moonbase/moonbase.o \ + he/moonbase/moonbase_fow.o endif # This module can be built as a plugin diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index e986ae4b47..68e4887b00 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Mon Mar 28 09:52:54 2016 + This file was generated by the md5table tool on Sat Apr 30 14:24:41 2016 DO NOT EDIT MANUALLY! */ @@ -532,6 +532,7 @@ static const MD5Table md5table[] = { { "bf8b52fdd9a69c67f34e8e9fec72661c", "farm", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, { "bfdf584b01503f0762baded581f6a0a2", "SoccerMLS", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, { "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", 26159, Common::NL_NLD, Common::kPlatformWindows }, + { "c0c9de81fb965e6cbe77f6e5631ca705", "monkey", "SE Talkie", "Unofficial SE Talkie v1.02", 9135, Common::EN_ANY, Common::kPlatformDOS }, { "c13225cb1bbd3bc9fe578301696d8021", "monkey", "SEGA", "", -1, Common::EN_ANY, Common::kPlatformSegaCD }, { "c20848f53c2d48bfacdc840993843765", "freddi2", "HE 80", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "c225bec1b6c0798a2b8c89ac226dc793", "pajama", "HE 101", "", -1, Common::EN_ANY, Common::kPlatformWii }, @@ -672,6 +673,7 @@ static const MD5Table md5table[] = { { "f3c5d9bf3f091bd1f18dc1013fba5396", "atlantis", "Steam", "Steam", 638976, Common::EN_ANY, Common::kPlatformWindows }, { "f3d55aea441e260e9e9c7d2a187097e0", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows }, { "f40a7f495f59188ca57a9d1d50301bb6", "puttputt", "HE 60", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "f4d20ab4ce19743a646cb48bd93aee72", "monkey2", "SE Talkie", "Unofficial SE Talkie v0.2", 10835, Common::EN_ANY, Common::kPlatformDOS }, { "f5228b0cc1c19e6ea8268ba2eeb61f60", "freddi", "HE 73", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "f73883f13b5a302749a5bad31d909780", "tentacle", "", "CD", -1, Common::DE_DEU, Common::kPlatformMacintosh }, { "f7635a0e2ab82c9a0f9ace5f232a488f", "catalog", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index e7118616ba..40f636c18f 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -66,6 +66,7 @@ #include "scumm/players/player_v5m.h" #include "scumm/resource.h" #include "scumm/he/resource_he.h" +#include "scumm/he/moonbase/moonbase.h" #include "scumm/scumm_v0.h" #include "scumm/scumm_v8.h" #include "scumm/sound.h" @@ -733,7 +734,7 @@ ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr) VAR_ACTIVE_VERB = 0xFF; if (strcmp(dr.fp.pattern, "maniacdemo.d64") == 0 ) - _game.features |= GF_DEMO; + _game.features |= GF_DEMO; } ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr) @@ -832,9 +833,16 @@ ScummEngine_v71he::ScummEngine_v71he(OSystem *syst, const DetectorResult &dr) _skipProcessActors = 0; VAR_WIZ_TCOLOR = 0xFF; + + /* Moonbase stuff */ + _moonbase = 0; + + if (_game.id == GID_MOONBASE) + _moonbase = new Moonbase(this); } ScummEngine_v71he::~ScummEngine_v71he() { + delete _moonbase; delete _wiz; } diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.h b/engines/sherlock/tattoo/tattoo_fixed_text.h index 7dbe13bbb3..eb636cdada 100644 --- a/engines/sherlock/tattoo/tattoo_fixed_text.h +++ b/engines/sherlock/tattoo/tattoo_fixed_text.h @@ -233,7 +233,7 @@ public: virtual const Common::String getActionMessage(FixedTextActionId actionId, int messageIndex); }; -} // End of namespace Scalpel +} // End of namespace Tattoo } // End of namespace Sherlock diff --git a/engines/sherlock/tattoo/tattoo_journal.cpp b/engines/sherlock/tattoo/tattoo_journal.cpp index 8e1a61d36e..4d4f37f8d5 100644 --- a/engines/sherlock/tattoo/tattoo_journal.cpp +++ b/engines/sherlock/tattoo/tattoo_journal.cpp @@ -50,7 +50,7 @@ void TattooJournal::show() { Screen &screen = *_vm->_screen; TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; byte palette[PALETTE_SIZE]; - + Common::Point oldScroll = screen._currentScroll; screen._currentScroll = Common::Point(0, 0); @@ -66,7 +66,7 @@ void TattooJournal::show() { // Set screen to black, and set background screen._backBuffer1.SHblitFrom((*_journalImages)[0], Common::Point(0, 0)); - screen.empty(); + screen.clear(); screen.setPalette(palette); if (_journal.empty()) { @@ -87,12 +87,12 @@ void TattooJournal::show() { handleKeyboardEvents(); highlightJournalControls(true); - + handleButtons(); if (_wait) events.wait(2); - + } while (!_vm->shouldQuit() && !_exitJournal); // Clear events @@ -275,7 +275,7 @@ void TattooJournal::handleButtons() { if (frameCounter >= _scrollingTimer) { // Set next scrolling time _scrollingTimer = frameCounter + 6; - + // Handle different scrolling actions switch (_selector) { case JH_SCROLL_LEFT: @@ -355,13 +355,13 @@ void TattooJournal::handleButtons() { _savedIndex = _index; _savedSub = _sub; _savedPage = _page; - + bool drawResult = drawJournal(dir + 2, 1000 * LINES_PER_PAGE); if (!drawResult) { _index = _savedIndex; _sub = _savedSub; _page = _savedPage; - + drawFrame(); drawJournal(0, 0); notFound = true; @@ -539,7 +539,7 @@ void TattooJournal::drawControls(int mode) { _oldSelector = 100; switch (mode) { - case 0: + case 0: highlightJournalControls(false); break; case 1: @@ -548,7 +548,7 @@ void TattooJournal::drawControls(int mode) { default: break; } - + _oldSelector = savedSelector; } @@ -558,7 +558,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) { Common::Point mousePos = events.mousePos(); Common::Rect r(JOURNAL_BAR_WIDTH, BUTTON_SIZE + screen.fontHeight() + 13); r.moveTo((SHERLOCK_SCREEN_WIDTH - r.width()) / 2, SHERLOCK_SCREEN_HEIGHT - r.height()); - + if ((events._pressed || events._released) && _selector == JH_THUMBNAIL) { if (events._released) _selector = JH_NONE; @@ -576,7 +576,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) { _selector = JH_NONE; if (bounds.contains(mousePos)) _selector = (mousePos.x - r.left) / (r.width() / 3); - + else if (events._pressed && mousePos.y >= (r.top + screen.fontHeight() + 10) && mousePos.y < (r.top + screen.fontHeight() + 10 + BUTTON_SIZE)) { if (mousePos.x >= r.left && mousePos.x < (r.left + BUTTON_SIZE)) @@ -628,7 +628,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) { color = (_selector == JH_SAVE) ? COMMAND_HIGHLIGHTED : INFO_TOP; else color = INFO_BOTTOM; - screen.gPrint(Common::Point(xp - screen.stringWidth(FIXED(SaveJournal)) / 2, r.top + 5), + screen.gPrint(Common::Point(xp - screen.stringWidth(FIXED(SaveJournal)) / 2, r.top + 5), color, "%s", FIXED(SaveJournal)); // Draw the horizontal scrollbar @@ -701,7 +701,7 @@ void TattooJournal::drawScrollBar() { raised = _selector != JH_SCROLL_LEFT; screen._backBuffer1.fillRect(Common::Rect(r.left, r.top + screen.fontHeight() + 12, r.left + BUTTON_SIZE, r.top + screen.fontHeight() + BUTTON_SIZE + 9), INFO_MIDDLE); - ui.drawDialogRect(screen._backBuffer1, Common::Rect(r.left + 3, r.top + screen.fontHeight() + 10, r.left + 3 + BUTTON_SIZE, + ui.drawDialogRect(screen._backBuffer1, Common::Rect(r.left + 3, r.top + screen.fontHeight() + 10, r.left + 3 + BUTTON_SIZE, r.top + screen.fontHeight() + 10 + BUTTON_SIZE), raised); color = (_page > 1) ? INFO_BOTTOM + 2 : INFO_BOTTOM; @@ -716,15 +716,15 @@ void TattooJournal::drawScrollBar() { // Draw the Scroll Right button raised = _selector != JH_SCROLL_RIGHT; - screen._backBuffer1.fillRect(Common::Rect(r.right - BUTTON_SIZE - 1, r.top + screen.fontHeight() + 12, + screen._backBuffer1.fillRect(Common::Rect(r.right - BUTTON_SIZE - 1, r.top + screen.fontHeight() + 12, r.right - 5, r.top + screen.fontHeight() + BUTTON_SIZE + 9), INFO_MIDDLE); ui.drawDialogRect(screen._backBuffer1, Common::Rect(r.right - BUTTON_SIZE - 3, r.top + screen.fontHeight() + 10, r.right - 3, r.top + screen.fontHeight() + BUTTON_SIZE + 9), raised); color = _down ? INFO_BOTTOM + 2 : INFO_BOTTOM; - screen._backBuffer1.vLine(r.right - 1 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 10 + BUTTON_SIZE / 2, + screen._backBuffer1.vLine(r.right - 1 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 10 + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 10 + BUTTON_SIZE / 2, color); - screen._backBuffer1.vLine(r.right - 2 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 9 + BUTTON_SIZE / 2, + screen._backBuffer1.vLine(r.right - 2 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 9 + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 11 + BUTTON_SIZE / 2, color); screen._backBuffer1.vLine(r.right - 3 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 8 + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 12 + BUTTON_SIZE / 2, color); @@ -776,14 +776,14 @@ int TattooJournal::getFindName(bool printError) { drawControls(1); disableControls(); - + // Backup the area under the text entry Surface bgSurface(r.width() - 6, screen.fontHeight()); - bgSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY, + bgSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY, r.right - 3, cursorY + screen.fontHeight())); if (printError) { - screen.gPrint(Common::Point(r.left + (r.width() - screen.stringWidth(FIXED(TextNotFound))) / 2, cursorY), + screen.gPrint(Common::Point(r.left + (r.width() - screen.stringWidth(FIXED(TextNotFound))) / 2, cursorY), INFO_TOP, "%s", FIXED(TextNotFound)); } else { // If there was a name already entered, copy it to name and display it @@ -977,7 +977,7 @@ void TattooJournal::saveJournal() { int line = 0; // Copy all of the talk files entries into one big string - do { + do { if (_lines[line].hasPrefix("@")) { text += Common::String(_lines[line].c_str() + 1); if ((line + 1) < (int)_lines.size() && _lines[line + 1].hasPrefix("@")) @@ -992,7 +992,7 @@ void TattooJournal::saveJournal() { // which show up as a blank line with the next line starting // with a '@'. We have to add a line break here because the '@' handler // previously assumes that they're always following a blank line - + if ((_lines[line].empty() || _lines[line] == " ") && (line + 1) < (int)_lines.size() && _lines[line + 1].hasPrefix("@")) text += "\n"; @@ -1005,7 +1005,7 @@ void TattooJournal::saveJournal() { do { if (text.size() > 80) { const char *msgP = text.c_str() + 80; - + if (Common::String(text.c_str(), msgP).contains("\n")) { // The 80 characters contain a carriage return, // so we can print out that line @@ -1013,7 +1013,7 @@ void TattooJournal::saveJournal() { file->writeString(Common::String(text.c_str(), cr)); text = Common::String(cr + 1); } else { - // Move backwards to find a word break + // Move backwards to find a word break while (*msgP != ' ') --msgP; diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h index e0d53c67dd..c844d86e19 100644 --- a/engines/sherlock/tattoo/tattoo_people.h +++ b/engines/sherlock/tattoo/tattoo_people.h @@ -273,9 +273,8 @@ public: virtual void setListenSequence(int speaker, int sequenceNum = 1); }; -} // End of namespace Scalpel +} // End of namespace Tattoo } // End of namespace Sherlock - #endif diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp index 9f78234aba..99e6daa756 100644 --- a/engines/sky/control.cpp +++ b/engines/sky/control.cpp @@ -167,7 +167,7 @@ ControlStatus::~ControlStatus() { void ControlStatus::setToText(const char *newText) { char tmpLine[256]; - strcpy(tmpLine, newText); + Common::strlcpy(tmpLine, newText, 256); if (_textData) { _statusText->flushForRedraw(); free(_textData); diff --git a/engines/sword2/screen.cpp b/engines/sword2/screen.cpp index 0cb951fdfc..40baf67e46 100644 --- a/engines/sword2/screen.cpp +++ b/engines/sword2/screen.cpp @@ -1296,7 +1296,7 @@ void Screen::setPsxScrCache(byte *psxScrCache, uint8 level) { } byte *Screen::getPsxScrCache(uint8 level) { - if (level > 3) { + if (level > 2) { level = 0; } @@ -1307,7 +1307,7 @@ byte *Screen::getPsxScrCache(uint8 level) { } bool Screen::getPsxScrCacheStatus(uint8 level) { - if (level > 3) { + if (level > 2) { level = 0; } diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp index a678fdccad..5d35a4f47e 100644 --- a/engines/sword25/gfx/image/vectorimage.cpp +++ b/engines/sword25/gfx/image/vectorimage.cpp @@ -217,6 +217,7 @@ Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, const Common::String &fname) : _pixelData(0), _fname(fname) { success = false; + _bgColor = 0; // Create bitstream object // In the following the file data will be readout of the bitstream object. diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp index c109e49aa8..92d39c252d 100644 --- a/engines/sword25/gfx/renderobject.cpp +++ b/engines/sword25/gfx/renderobject.cpp @@ -71,19 +71,18 @@ RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type, _version(++_nextGlobalVersion), _isSolid(false) { - // Renderobject registrieren, abhängig vom Handle-Parameter entweder mit beliebigem oder vorgegebenen Handle. if (handle == 0) _handle = RenderObjectRegistry::instance().registerObject(this); else _handle = RenderObjectRegistry::instance().registerObject(this, handle); if (_handle == 0) - return; + error("Failed to initialize RenderObject()"); updateAbsolutePos(); - // Dieses Objekt zu den Kindern der Elternobjektes hinzufügen, falls nicht Wurzel (ParentPtr ungültig) und dem - // selben RenderObjektManager zuweisen. + // Add this item to the children of the parent object, if not root (ParentPtr is invalid), + // assign to the same RenderObjectManager. if (_parentPtr.isValid()) { _managerPtr = _parentPtr->getManager(); _parentPtr->addObject(this->getHandle()); @@ -100,24 +99,22 @@ RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type, } RenderObject::~RenderObject() { - // Objekt aus dem Elternobjekt entfernen. + // Remove object from its parent. if (_parentPtr.isValid()) _parentPtr->detatchChildren(this->getHandle()); deleteAllChildren(); - // Objekt deregistrieren. RenderObjectRegistry::instance().deregisterObject(this); } void RenderObject::preRender(RenderObjectQueue *renderQueue) { - // Objektänderungen validieren validateObject(); if (!_visible) return; - // Falls notwendig, wird die Renderreihenfolge der Kinderobjekte aktualisiert. + // If necessary, update the children rendering order of the updated objects. if (_childChanged) { sortRenderObjects(); _childChanged = false; @@ -149,7 +146,7 @@ bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> & if (needRender) doRender(updateRects); - // Dann müssen die Kinder gezeichnet werden + // Draw all children RENDEROBJECT_ITER it = _children.begin(); for (; it != _children.end(); ++it) if (!(*it)->render(updateRects, updateRectsMinZ)) @@ -159,7 +156,6 @@ bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> & } void RenderObject::validateObject() { - // Die Veränderungen in den Objektvariablen aufheben _oldBbox = _bbox; _oldVisible = _visible; _oldX = _x; @@ -169,15 +165,14 @@ void RenderObject::validateObject() { } bool RenderObject::updateObjectState() { - // Falls sich das Objekt verändert hat, muss der interne Zustand neu berechnet werden und evtl. Update-Regions für den nächsten Frame - // registriert werden. + // If the object has changed, the internal state must be recalculated and possibly + // update Regions be registered for the next frame. if ((calcBoundingBox() != _oldBbox) || (_visible != _oldVisible) || (_x != _oldX) || (_y != _oldY) || (_z != _oldZ) || _refreshForced) { - // Renderrang des Objektes neu bestimmen, da sich dieser verändert haben könnte if (_parentPtr.isValid()) _parentPtr->signalChildChange(); @@ -200,12 +195,10 @@ bool RenderObject::updateObjectState() { } void RenderObject::updateBoxes() { - // Bounding-Box aktualisieren _bbox = calcBoundingBox(); } Common::Rect RenderObject::calcBoundingBox() const { - // Die Bounding-Box mit der Objektgröße initialisieren. Common::Rect bbox(0, 0, _width, _height); // Die absolute Position der Bounding-Box berechnen. @@ -247,8 +240,6 @@ int32 RenderObject::calcAbsoluteZ() const { } void RenderObject::deleteAllChildren() { - // Es ist nicht notwendig die Liste zu iterieren, da jedes Kind für sich DetatchChildren an diesem Objekt aufruft und sich somit - // selber entfernt. Daher muss immer nur ein beliebiges Element (hier das letzte) gelöscht werden, bis die Liste leer ist. while (!_children.empty()) { RenderObjectPtr<RenderObject> curPtr = _children.back(); curPtr.erase(); @@ -261,10 +252,10 @@ bool RenderObject::addObject(RenderObjectPtr<RenderObject> pObject) { return false; } - // Objekt in die Kinderliste einfügen. + // Insert Object in the children list. _children.push_back(pObject); - // Sicherstellen, dass vor dem nächsten Rendern die Renderreihenfolge aktualisiert wird. + // Make sure that before the next render the channel order is updated. if (_parentPtr.isValid()) _parentPtr->signalChildChange(); diff --git a/engines/teenagent/music.cpp b/engines/teenagent/music.cpp index 5d66c3c90c..795b8f7312 100644 --- a/engines/teenagent/music.cpp +++ b/engines/teenagent/music.cpp @@ -36,7 +36,7 @@ static const uint32 noteToPeriod[3][12] = { {214, 201, 189, 179, 170, 160, 151, 143, 135, 127, 120, 113} }; -MusicPlayer::MusicPlayer(TeenAgentEngine *vm) : Paula(false, 44100, 5000), _vm(vm), _id(0) { +MusicPlayer::MusicPlayer(TeenAgentEngine *vm) : Paula(false, 44100, 5000), _vm(vm), _id(0), _currRow(0) { } MusicPlayer::~MusicPlayer() { @@ -55,7 +55,7 @@ bool MusicPlayer::load(int id) { Common::StackLock lock(_mutex); // Load the samples - sampleCount = stream->readByte(); + byte sampleCount = stream->readByte(); debugC(0, kDebugMusic, "sampleCount = %d", sampleCount); diff --git a/engines/teenagent/music.h b/engines/teenagent/music.h index e1630cc845..4b1b683a30 100644 --- a/engines/teenagent/music.h +++ b/engines/teenagent/music.h @@ -74,7 +74,6 @@ private: size = 0; } } _samples[256]; - byte sampleCount; Common::Array<Row> _rows; uint _currRow; diff --git a/engines/teenagent/objects.h b/engines/teenagent/objects.h index f923ae52ab..1f8a82a66e 100644 --- a/engines/teenagent/objects.h +++ b/engines/teenagent/objects.h @@ -165,7 +165,7 @@ struct Object { //19 Common::String name, description; - Object(): _base(NULL) {} + Object(): _base(NULL) { id = 0; actorOrientation = 0; enabled = 0; } void dump(int level = 0) const; void setName(const Common::String &newName); void load(byte *addr); @@ -205,7 +205,7 @@ struct Walkbox { Rect rect; byte sideHint[4]; - Walkbox() : _base(NULL) {} + Walkbox() : _base(NULL) { memset(this, 0, sizeof(Walkbox)); } void dump(int level = 0) const; void load(byte *src); void save() const; diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp index 6e1cef31bc..c250269844 100644 --- a/engines/teenagent/scene.cpp +++ b/engines/teenagent/scene.cpp @@ -71,6 +71,9 @@ Scene::Scene(TeenAgentEngine *vm) : _vm(vm), intro(false), _id(0), ons(0), varia.close(); loadObjectData(); + + _onsCount = 0; + _messageColor = 0; } Scene::~Scene() { @@ -314,7 +317,7 @@ void Scene::loadOns() { uint16 addr = _vm->res->dseg.get_word(dsAddr_onsAnimationTablePtr + (_id - 1) * 2); debugC(0, kDebugScene, "ons index: %04x", addr); - onsCount = 0; + _onsCount = 0; byte b; byte onId[16]; while ((b = _vm->res->dseg.get_byte(addr)) != 0xff) { @@ -323,15 +326,15 @@ void Scene::loadOns() { if (b == 0) continue; - onId[onsCount++] = b; + onId[_onsCount++] = b; } delete[] ons; ons = NULL; - if (onsCount > 0) { - ons = new Surface[onsCount]; - for (uint32 i = 0; i < onsCount; ++i) { + if (_onsCount > 0) { + ons = new Surface[_onsCount]; + for (uint32 i = 0; i < _onsCount; ++i) { Common::ScopedPtr<Common::SeekableReadStream> s(_vm->res->ons.getStream(onId[i])); if (s) { ons[i].load(*s, Surface::kTypeOns); @@ -498,7 +501,7 @@ bool Scene::processEvent(const Common::Event &event) { events.clear(); sounds.clear(); currentEvent.clear(); - messageColor = textColorMark; + _messageColor = textColorMark; for (int i = 0; i < 4; ++i) customAnimation[i].free(); _vm->playMusic(4); @@ -651,7 +654,7 @@ bool Scene::render(bool tickGame, bool tickMark, uint32 messageDelta) { bool gotAnyAnimation = false; if (ons != NULL && debugFeatures.feature[DebugFeatures::kShowOns]) { - for (uint32 i = 0; i < onsCount; ++i) { + for (uint32 i = 0; i < _onsCount; ++i) { Surface *s = ons + i; if (s != NULL) s->render(surface); @@ -821,7 +824,7 @@ bool Scene::render(bool tickGame, bool tickMark, uint32 messageDelta) { } if (visible) { - _vm->res->font7.render(surface, messagePos.x, messagePos.y, message, messageColor); + _vm->res->font7.render(surface, messagePos.x, messagePos.y, message, _messageColor); busy = true; } } @@ -1005,7 +1008,7 @@ bool Scene::processEventQueue() { warning("no animation in slot %u", messageSlot); } messagePos = messagePosition(message, p); - messageColor = currentEvent.color; + _messageColor = currentEvent.color; if (messageFirstFrame) currentEvent.clear(); // async message, clearing event @@ -1153,7 +1156,7 @@ bool Scene::processEventQueue() { } if (events.empty()) { - messageColor = textColorMark; + _messageColor = textColorMark; hideActor = false; } @@ -1232,7 +1235,7 @@ void Scene::displayMessage(const Common::String &str, byte color, const Common:: debugC(0, kDebugScene, "displayMessage: %s", str.c_str()); message = str; messagePos = (pos.x | pos.y) ? pos : messagePosition(str, position); - messageColor = color; + _messageColor = color; messageTimer = messageDuration(message); } @@ -1251,7 +1254,7 @@ void Scene::clear() { void Scene::clearMessage() { message.clear(); messageTimer = 0; - messageColor = textColorMark; + _messageColor = textColorMark; messageFirstFrame = 0; messageLastFrame = 0; messageAnimation = NULL; diff --git a/engines/teenagent/scene.h b/engines/teenagent/scene.h index 07b304ed97..40f910a3aa 100644 --- a/engines/teenagent/scene.h +++ b/engines/teenagent/scene.h @@ -194,7 +194,7 @@ private: SurfaceList on; bool onEnabled; Surface *ons; - uint32 onsCount; + uint32 _onsCount; Animation actorAnimation, animation[4], customAnimation[4]; Common::Rect actorAnimationPosition, animationPosition[4]; @@ -214,7 +214,7 @@ private: Common::String message; Common::Point messagePos; - byte messageColor; + byte _messageColor; uint messageTimer; byte messageFirstFrame; byte messageLastFrame; diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp index 4dc785754c..2d10b82f51 100644 --- a/engines/teenagent/teenagent.cpp +++ b/engines/teenagent/teenagent.cpp @@ -71,6 +71,13 @@ TeenAgentEngine::TeenAgentEngine(OSystem *system, const ADGameDescription *gd) res = new Resources(); console = 0; + scene = 0; + inventory = 0; + _sceneBusy = false; + _dstObject = 0; + _musicStream = 0; + _markDelay = 0; + _gameDelay = 0; } TeenAgentEngine::~TeenAgentEngine() { diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp index 22c3798fc6..cfe97e6ec1 100644 --- a/engines/tinsel/bmv.cpp +++ b/engines/tinsel/bmv.cpp @@ -567,8 +567,8 @@ void BMVPlayer::PlayBMV(CORO_PARAM, SCNHANDLE hFileStem, int myEscape) { assert(!bMovieOn); - strcpy(szMovieFile, (char *)LockMem(hFileStem)); - strcat(szMovieFile, BMOVIE_EXTENSION); + Common::strlcpy(szMovieFile, (char *)LockMem(hFileStem), 14); + Common::strlcat(szMovieFile, BMOVIE_EXTENSION, 14); assert(strlen(szMovieFile) <= 12); diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index 2fde6e788a..c44f1f4ef3 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -235,7 +235,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) { // Get the next filename, stripping off any '1' suffix character char tempFilename[50]; - strcpy(tempFilename, fileDesc->fileName); + Common::strlcpy(tempFilename, fileDesc->fileName, 50); char *pOne = strchr(tempFilename, '1'); if (pOne) { do { @@ -275,7 +275,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) { // Get the next filename, stripping off any '1' suffix character char tempFilename[50]; - strcpy(tempFilename, fileDesc->fileName); + Common::strlcpy(tempFilename, fileDesc->fileName, 50); char *pOne = strchr(tempFilename, '1'); if (pOne) { do { diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index a84dad942c..ad20253b9c 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -1671,10 +1671,10 @@ static void Select(int i, bool force) { #else // Current description with cursor appended if (cd.box[i].boxText != NULL) { - strcpy(g_sedit, cd.box[i].boxText); - strcat(g_sedit, sCursor); + Common::strlcpy(g_sedit, cd.box[i].boxText, SG_DESC_LEN+2); + Common::strlcat(g_sedit, sCursor, SG_DESC_LEN+2); } else { - strcpy(g_sedit, sCursor); + Common::strlcpy(g_sedit, sCursor, SG_DESC_LEN+2); } #endif @@ -3676,13 +3676,13 @@ extern void HideConversation(bool bHide) { ConstructInventory(FULL); else { // Move it all back on-screen - for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { + for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) { MultiAdjustXY(g_objArray[i], -2 * SCREEN_WIDTH, 0); } // Don't flash if items changed. If they have, will be redrawn anyway. if (TinselV2 || !g_ItemsChanged) { - for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { + for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) { MultiAdjustXY(g_iconArray[i], -2*SCREEN_WIDTH, 0); } } @@ -3739,10 +3739,10 @@ extern void HideConversation(bool bHide) { deltay = g_InvD[INV_CONV].inventoryY - deltay; // Move it all - for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { + for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) { MultiMoveRelXY(g_objArray[i], x - center, deltay); } - for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { + for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) { MultiMoveRelXY(g_iconArray[i], x - center, deltay); } g_InvD[INV_CONV].inventoryX += x - center; @@ -3771,10 +3771,10 @@ extern void HideConversation(bool bHide) { y = 0; if (x || y) { - for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { + for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) { MultiMoveRelXY(g_objArray[i], x, y); } - for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { + for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) { MultiMoveRelXY(g_iconArray[i], x, y); } g_InvD[INV_CONV].inventoryX += x; @@ -3786,10 +3786,10 @@ extern void HideConversation(bool bHide) { */ if (MultiLowest(g_RectObject) > SCREEN_BOX_HEIGHT2 - SysVar(SV_CONV_MINY)) { y = (SCREEN_BOX_HEIGHT2 - SysVar(SV_CONV_MINY)) - MultiLowest(g_RectObject); - for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { + for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) { MultiMoveRelXY(g_objArray[i], 0, y); } - for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { + for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) { MultiMoveRelXY(g_iconArray[i], 0, y); } g_InvD[INV_CONV].inventoryY += y; diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index 62d244e449..9ffd477c4a 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -258,7 +258,7 @@ void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) { } void SetCdPlaySceneDetails(int fileNum, const char *fileName) { - strcpy(g_szCdPlayFile, fileName); + Common::strlcpy(g_szCdPlayFile, fileName, 100); } void SetCdPlayHandle(int fileNum) { diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp index 88cd80b78a..226cbb51c0 100644 --- a/engines/tinsel/saveload.cpp +++ b/engines/tinsel/saveload.cpp @@ -563,7 +563,7 @@ static void DoSave() { while (1) { Common::String fname = _vm->getSavegameFilename(ano); - strcpy(tmpName, fname.c_str()); + Common::strlcpy(tmpName, fname.c_str(), FNAMELEN); for (i = 0; i < g_numSfiles; i++) if (!strcmp(g_savedFiles[i].name, tmpName)) diff --git a/engines/toltecs/movie.cpp b/engines/toltecs/movie.cpp index b64903ec6d..b26408fadc 100644 --- a/engines/toltecs/movie.cpp +++ b/engines/toltecs/movie.cpp @@ -45,7 +45,7 @@ enum ChunkTypes { kChunkStopSubtitles = 8 }; -MoviePlayer::MoviePlayer(ToltecsEngine *vm) : _vm(vm), _isPlaying(false), _lastPrefetchOfs(0), _framesPerSoundChunk(0), _endPos(0) { +MoviePlayer::MoviePlayer(ToltecsEngine *vm) : _vm(vm), _isPlaying(false), _lastPrefetchOfs(0), _framesPerSoundChunk(0), _endPos(0), _audioStream(0) { } MoviePlayer::~MoviePlayer() { diff --git a/engines/toltecs/resource.cpp b/engines/toltecs/resource.cpp index 468ae0272f..6dbb9c2843 100644 --- a/engines/toltecs/resource.cpp +++ b/engines/toltecs/resource.cpp @@ -31,6 +31,7 @@ namespace Toltecs { /* ArchiveReader */ ArchiveReader::ArchiveReader() { + _offsets = 0; } ArchiveReader::~ArchiveReader() { diff --git a/engines/toltecs/sprite.cpp b/engines/toltecs/sprite.cpp index f29f64dcfe..be4be5d9e3 100644 --- a/engines/toltecs/sprite.cpp +++ b/engines/toltecs/sprite.cpp @@ -84,6 +84,7 @@ public: _yerror = _sprite->yerror; _origHeight = _sprite->origHeight; _scalerStatus = 0; + _xerror = 0; } SpriteReaderStatus readPacket(PixelPacket &packet) { SpriteReaderStatus status = kSrsPixelsLeft; @@ -135,6 +136,8 @@ public: _yerror = _sprite->yerror; _origHeight = _sprite->origHeight; _scalerStatus = 0; + _sourcep = 0; + _xerror = 0; } SpriteReaderStatus readPacket(PixelPacket &packet) { SpriteReaderStatus status; diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp index 2a32926c53..27145d7c4b 100644 --- a/engines/tony/gfxcore.cpp +++ b/engines/tony/gfxcore.cpp @@ -1733,13 +1733,6 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri g /= 5; b /= 5; - if (r > 0x1f) - r = 0x1f; - if (g > 0x3f) - g = 0x3f; - if (b > 0x1f) - b = 0x1f; - mybuf[0] = (r << 11) | (g << 5) | b; } } @@ -1774,13 +1767,6 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri g /= 6; b /= 6; - if (r > 0x1f) - r = 0x1f; - if (g > 0x3f) - g = 0x3f; - if (b > 0x1f) - b = 0x1f; - mybuf[0] = (r << 11) | (g << 5) | b; } } diff --git a/engines/tony/mpal/loadmpc.cpp b/engines/tony/mpal/loadmpc.cpp index 8d030f1e52..01892a40e6 100644 --- a/engines/tony/mpal/loadmpc.cpp +++ b/engines/tony/mpal/loadmpc.cpp @@ -331,7 +331,7 @@ static const byte *parseItem(const byte *lpBuf, LpMpalItem lpmiItem) { byte len = *lpBuf; lpBuf++; - memcpy(lpmiItem->_lpszDescribe, lpBuf, MIN((byte)127, len)); + memcpy(lpmiItem->_lpszDescribe, lpBuf, MIN((byte)MAX_DESCRIBE_SIZE, len)); lpBuf += len; if (len >= MAX_DESCRIBE_SIZE) diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index 89cc28130d..9172843781 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -367,12 +367,18 @@ MpalHandle resLoad(uint32 dwId) { temp = (byte *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, nSizeComp); nBytesRead = GLOBALS._hMpr.read(temp, nSizeComp); - if (nBytesRead != nSizeComp) + if (nBytesRead != nSizeComp) { + globalDestroy(temp); + globalDestroy(h); return NULL; + } lzo1x_decompress(temp, nSizeComp, buf, &nBytesRead); - if (nBytesRead != nSizeDecomp) + if (nBytesRead != nSizeDecomp) { + globalDestroy(temp); + globalDestroy(h); return NULL; + } globalDestroy(temp); globalUnlock(h); @@ -526,8 +532,10 @@ static LpItem getItemData(uint32 nOrdItem) { globalFree(hDat); // Check if we've got to the end of the file - if (i != 0xABCD) + if (i != 0xABCD) { + globalDestroy(ret); return NULL; + } return ret; } @@ -1413,36 +1421,51 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName, if (bCompress) { // Get the compressed size and read the data in uint32 dwSizeComp = hMpc.readUint32LE(); - if (hMpc.err()) + if (hMpc.err()) { + globalDestroy(lpMpcImage); return false; + } cmpbuf = (byte *)globalAlloc(GMEM_FIXED, dwSizeComp); - if (cmpbuf == NULL) + if (cmpbuf == NULL) { + globalDestroy(lpMpcImage); return false; + } nBytesRead = hMpc.read(cmpbuf, dwSizeComp); - if (nBytesRead != dwSizeComp) + if (nBytesRead != dwSizeComp) { + globalDestroy(cmpbuf); + globalDestroy(lpMpcImage); return false; + } // Decompress the data lzo1x_decompress(cmpbuf, dwSizeComp, lpMpcImage, &nBytesRead); - if (nBytesRead != dwSizeDecomp) + if (nBytesRead != dwSizeDecomp) { + globalDestroy(cmpbuf); + globalDestroy(lpMpcImage); return false; + } globalDestroy(cmpbuf); } else { // If the file is not compressed, we directly read in the data nBytesRead = hMpc.read(lpMpcImage, dwSizeDecomp); - if (nBytesRead != dwSizeDecomp) + if (nBytesRead != dwSizeDecomp) { + globalDestroy(lpMpcImage); return false; + } } // Close the file hMpc.close(); // Process the data - if (parseMpc(lpMpcImage) == false) + if (parseMpc(lpMpcImage) == false) { + globalDestroy(lpMpcImage); + return false; + } globalDestroy(lpMpcImage); diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp index bd8a0cdd0d..6b44ecc514 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp @@ -1440,7 +1440,7 @@ void Scene2425::postInit(SceneObjectList *OwnerList) { case 2425: _sceneMode = 10; R2_GLOBALS._player.setPosition(Common::Point(280, 150)); - _action->signal(); + signal(); break; case 2455: _sceneMode = 2428; diff --git a/engines/wage/macmenu.cpp b/engines/wage/macmenu.cpp index a97e442c83..ed5f5070ff 100644 --- a/engines/wage/macmenu.cpp +++ b/engines/wage/macmenu.cpp @@ -104,6 +104,9 @@ Menu::Menu(int id, const Common::Rect &bounds, MacWindowManager *wm) _activeItem = -1; _activeSubItem = -1; + _ccallback = NULL; + _cdata = NULL; + _tempSurface.create(_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8()); } diff --git a/engines/wage/macwindow.cpp b/engines/wage/macwindow.cpp index 7ff0f57ccb..8903936061 100644 --- a/engines/wage/macwindow.cpp +++ b/engines/wage/macwindow.cpp @@ -76,6 +76,8 @@ MacWindow::MacWindow(int id, bool scrollable, bool resizable, bool editable, Mac _beingDragged = false; _beingResized = false; + _draggedX = _draggedY = 0; + _type = kWindowWindow; } diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp index 2166a3e070..4ce334aceb 100644 --- a/engines/wintermute/base/base_engine.cpp +++ b/engines/wintermute/base/base_engine.cpp @@ -84,7 +84,7 @@ void BaseEngine::LOG(bool res, const char *fmt, ...) { va_end(va); if (instance()._gameRef) { - instance()._gameRef->LOG("%s", buff); + instance()._gameRef->LOG(res, "%s", buff); } else { debugCN(kWintermuteDebugLog, "%02d:%02d:%02d: %s\n", hours, mins, secs, buff); } diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp index b10b4fb5fe..0b2ea9fd4e 100644 --- a/gui/widgets/popup.cpp +++ b/gui/widgets/popup.cpp @@ -388,6 +388,8 @@ PopUpWidget::PopUpWidget(GuiObject *boss, int x, int y, int w, int h, const char _type = kPopUpWidget; _selectedItem = -1; + + _leftPadding = _rightPadding = 0; } void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) { diff --git a/po/de_DE.po b/po/de_DE.po index 2943f18bfa..65765ecca0 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: ScummVM 1.9.0git\n" "Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" -"POT-Creation-Date: 2016-04-07 08:55+0100\n" -"PO-Revision-Date: 2016-04-15 11:00+0100\n" +"POT-Creation-Date: 2016-04-07 08:55+0200\n" +"PO-Revision-Date: 2016-05-01 15:45+0200\n" "Last-Translator: Lothar Serra Mari <rootfather@scummvm.org>\n" "Language-Team: Simon Sawatzki <SimSaw@gmx.de>, Lothar Serra Mari " "<rootfather@scummvm.org>\n" @@ -978,7 +978,7 @@ msgstr "Musiklautstärke:" #: gui/options.cpp:970 msgid "Mute All" -msgstr "Alles aus" +msgstr "Stumm" #: gui/options.cpp:973 msgid "SFX volume:" |