diff options
84 files changed, 2347 insertions, 947 deletions
diff --git a/.gitignore b/.gitignore index 3e80289a16..2ad104214e 100644 --- a/.gitignore +++ b/.gitignore @@ -166,6 +166,7 @@ ipch/ *.vcxproj* *.bat *.tss +*.VC.db #Ignore default Visual Studio build folders [Dd]ebug/ @@ -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/create_wage/create_wage.sh b/devtools/create_classicmacfonts.sh index 5e8fe352a2..6942d07111 100755 --- a/devtools/create_wage/create_wage.sh +++ b/devtools/create_classicmacfonts.sh @@ -106,8 +106,8 @@ echo_n "Converting fonts..." fondu-060102/fondu -force *.bin echo done -zip -9 wage *.bdf -mv wage.zip wage.dat +zip -9 classicmacfonts *.bdf +mv classicmacfonts.zip classicmacfonts.dat echo_n "Cleaning up..." rm *.bdf @@ -116,4 +116,4 @@ rm *.bin rm *.dmg echo done -ls -l wage.dat +ls -l classicmacfonts.dat 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/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/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/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/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/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h index 370f54c1d8..51d9a9045f 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -27,6 +27,8 @@ #ifdef ENABLE_HE #include "scumm/he/floodfill_he.h" #include "scumm/he/wiz_he.h" + +#include "scumm/he/moonbase/moonbase.h" #endif #include "scumm/actor_he.h" // For AuxBlock & AuxEntry @@ -186,6 +188,7 @@ protected: #ifdef ENABLE_HE 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.cpp deleted file mode 100644 index 29a0dde7a2..0000000000 --- a/engines/scumm/he/logic/moonbase.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* 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/logic_he.h" - -namespace Scumm { - -/** - * Logic code for: - * Moonbase Commander - */ -class LogicHEmoonbase : public LogicHE { -public: - LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {} - - int versionID(); -}; - -int LogicHEmoonbase::versionID() { - if (_vm->_game.features & GF_DEMO) - return -100; - else if (strcmp(_vm->_game.variant, "1.1") == 0) - return 110; - else - return 100; -} - -LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) { - return new LogicHEmoonbase(vm); -} - -} // End of namespace Scumm diff --git a/engines/scumm/he/logic/moonbase_logic.cpp b/engines/scumm/he/logic/moonbase_logic.cpp new file mode 100644 index 0000000000..5f02fa9cd4 --- /dev/null +++ b/engines/scumm/he/logic/moonbase_logic.cpp @@ -0,0 +1,231 @@ +/* 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/logic_he.h" + +namespace Scumm { + +/** + * Logic code for: + * Moonbase Commander + */ +class LogicHEmoonbase : public LogicHE { +public: + LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {} + + int versionID(); + + int32 dispatch(int op, int numArgs, int32 *args); + +private: + void op_create_multi_state_wiz(int op, int numArgs, int32 *args); + 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(int32 *args); + void op_set_fow_information(int op, int numArgs, int32 *args); + void 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); + void op_ai_set_type(int op, int numArgs, int32 *args); + void op_ai_clean_up(int op, int numArgs, int32 *args); +}; + +int LogicHEmoonbase::versionID() { + if (_vm->_game.features & GF_DEMO) + return -100; + else if (strcmp(_vm->_game.variant, "1.1") == 0) + return 110; + else + return 100; +} + +#define OP_CREATE_MULTI_STATE_WIZ 100 +#define OP_LOAD_MULTI_CHANNEL_WIZ 101 +#define OP_WIZ_FROM_MULTI_CHANNEL_WIZ 102 +#define OP_DOS_COMMAND 103 +#define OP_SET_FOW_SENTINEL 104 +#define OP_SET_FOW_INFORMATION 105 +#define OP_SET_FOW_IMAGE 106 + +#define OP_AI_TEST_KLUDGE 10000 +#define OP_AI_MASTER_CONTROL_PROGRAM 10001 +#define OP_AI_RESET 10002 +#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: + op_create_multi_state_wiz(op, numArgs, args); + break; + case OP_LOAD_MULTI_CHANNEL_WIZ: + op_load_multi_channel_wiz(op, numArgs, args); + break; + case OP_WIZ_FROM_MULTI_CHANNEL_WIZ: + op_wiz_from_multi_channel_wiz(op, numArgs, args); + break; + case OP_DOS_COMMAND: + op_dos_command(op, numArgs, args); + break; + case OP_SET_FOW_SENTINEL: + 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); + break; + + case OP_AI_TEST_KLUDGE: + op_ai_test_kludge(op, numArgs, args); + break; + case OP_AI_MASTER_CONTROL_PROGRAM: + op_ai_master_control_program(op, numArgs, args); + break; + case OP_AI_RESET: + op_ai_reset(op, numArgs, args); + break; + case OP_AI_SET_TYPE: + op_ai_set_type(op, numArgs, args); + break; + case OP_AI_CLEAN_UP: + op_ai_clean_up(op, numArgs, args); + break; + + default: + LogicHE::dispatch(op, numArgs, args); + } + + return 0; +} + +void LogicHEmoonbase::op_create_multi_state_wiz(int op, int numArgs, int32 *args) { + warning("STUB: op_create_multi_state_wiz()"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_load_multi_channel_wiz(int op, int numArgs, int32 *args) { + warning("STUB: op_load_multi_channel_wiz()"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *args) { + warning("STUB: op_wiz_from_multi_channel_wiz()"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_dos_command(int op, int numArgs, int32 *args) { + warning("STUB: op_dos_command()"); + 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); +} + +void LogicHEmoonbase::op_set_fow_image(int op, int numArgs, int32 *args) { + warning("STUB: op_set_fow_image()"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_test_kludge(int op, int numArgs, int32 *args) { + warning("STUB: op_ai_test_kludge()"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) { + warning("STUB: op_ai_master_control_program()"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_reset(int op, int numArgs, int32 *args) { + warning("STUB: op_ai_reset)"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_set_type(int op, int numArgs, int32 *args) { + warning("STUB: op_ai_set_type()"); + LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_clean_up(int op, int numArgs, int32 *args) { + warning("STUB: op_ai_clean_up()"); + LogicHE::dispatch(op, numArgs, args); +} + +LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) { + return new LogicHEmoonbase(vm); +} + +} // End of namespace Scumm diff --git a/engines/scumm/he/moonbase/moonbase.cpp b/engines/scumm/he/moonbase/moonbase.cpp new file mode 100644 index 0000000000..a07a874b48 --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.cpp @@ -0,0 +1,154 @@ +/* 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" + +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) { + + 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 + for (int c = 0; c < 4; c++) { + if (pixels >= sx) { + WRITE_LE_UINT16(dst1, READ_LE_UINT16(quadsOffset)); + dst1 += 2; + } + quadsOffset += 2; + pixels++; + } + } else if (code < 0) { // single + if (pixels >= sx) { + WRITE_LE_UINT16(dst1, READ_LE_UINT16(singlesOffset)); + dst1 += 2; + } + singlesOffset += 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); + + //WRITE_LE_UINT16(dst1, color); // ENABLE_PREMUL_ALPHA = 0 + // ENABLE_PREMUL_ALPHA = 2 + 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..e50337ddeb --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.h @@ -0,0 +1,95 @@ +/* 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 + +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: + bool captureFOWImageFromLocation(void *src); + 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; + uint16 _fowSentinelConditionBits; + +private: + ScummEngine_v71he *_vm; + + int _fowFrameBaseNumber; + int _fowAnimationFrames; + int _fowCurrentFOWFrame; + + int _fowTileW; + int _fowTileH; + + byte *_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]; +}; + +#endif + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/he/moonbase/moonbase_fow.cpp b/engines/scumm/he/moonbase/moonbase_fow.cpp new file mode 100644 index 0000000000..f76bebf89e --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase_fow.cpp @@ -0,0 +1,435 @@ +/* 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" + +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::captureFOWImageFromLocation(void *src) { + if (!src) + return false; + + int imageDataSize = 0; //getMemoryBlockSize(src); // TODO + + if (imageDataSize <= 0) + return false; + + _fowImage = (byte *)malloc(imageDataSize); + + if (!_fowImage) + return false; + + memcpy(_fowImage, src, imageDataSize); + + return true; +} + +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); + free(wiz); + } + } +#endif + + if (!_fowImage && image < 0) { + int resType; + + // PIECES BUBBLES CIRCLES SIMPLE* WEDGEY BUBBLE2 + // WEDGE2 SPIKEY ANGLES SMOOTHED WUZZY SYS7-BEVELED + if (image >= -1 && image <= 12) + resType = 210 - image; // 211-222 range + else + resType = 214; // default, SIMPLE +#if 0 // TODO + HRSRC hResource = FindResource(g_hInst, resType, 10); + if (hResource) { + byte res = LoadResource(g_hInst, hResource); + + if (res) { + uint16 nDataSize = SizeofResource(g_hInst, hResource); + + if (nDataSize) + captureFOWImageFromLocation(res); + } + } +#endif + } + + if (!_fowImage && image > 0) { + void *glob = _vm->getResourceAddress(rtImage, image); + + if (glob) + captureFOWImageFromLocation(glob); + } + + 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; + + Common::Point fowTileSize(0, 0); //getWizStateSize(_fowImage, (nStates - 1)); // TODO + + _fowTileW = fowTileSize.x; + _fowTileH = fowTileSize.y; + + int hitTestValue = 0; + uint pixelValue = 0; + + //LayeredWizHitTest(&hitTestValue, &pixelValue, _fowImage, (nStates - 1), 0, 0, 0, 0); // TODO + _fowBlackMode = (pixelValue == 0) ? 1 : 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(_vm->VAR_U32_ARRAY_UNK) = array; // TODO + + 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) { + int spotx, spoty; + + _vm->_wiz->getWizStateSpot(_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 afc6633ef6..7d56138247 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -1310,36 +1310,36 @@ void ScummEngine_v100he::o100_wizImageOps() { if (_wizParams.img.resNum) _wiz->processWizImage(&_wizParams); break; - case 128: - _wizParams.field_239D = pop(); - _wizParams.field_2399 = pop(); - _wizParams.field_23A5 = pop(); - _wizParams.field_23A1 = pop(); - copyScriptString(_wizParams.string2, sizeof(_wizParams.string2)); + case 128: // Font create _wizParams.processMode = 15; + _wizParams.fontProperties.bgColor = pop(); + _wizParams.fontProperties.fgColor = pop(); + _wizParams.fontProperties.size = pop(); + _wizParams.fontProperties.style = pop(); + copyScriptString(_wizParams.fontProperties.fontName, sizeof(_wizParams.fontProperties.fontName)); break; case 129: _wizParams.processMode = 14; break; - case 130: + case 130: // Font render _wizParams.processMode = 16; - _wizParams.field_23AD = pop(); - _wizParams.field_23A9 = pop(); - copyScriptString(_wizParams.string1, sizeof(_wizParams.string1)); + _wizParams.fontProperties.yPos = pop(); + _wizParams.fontProperties.xPos = pop(); + copyScriptString(_wizParams.fontProperties.string, sizeof(_wizParams.fontProperties.string)); break; case 131: _wizParams.processMode = 13; break; - case 133: + case 133: // Render ellipse _wizParams.processMode = 17; - _wizParams.field_23CD = pop(); - _wizParams.field_23C9 = pop(); - _wizParams.field_23C5 = pop(); - _wizParams.field_23C1 = pop(); - _wizParams.field_23BD = pop(); - _wizParams.field_23B9 = pop(); - _wizParams.field_23B5 = pop(); - _wizParams.field_23B1 = pop(); + _wizParams.ellipseProperties.color = pop(); + _wizParams.ellipseProperties.lod = pop(); + _wizParams.ellipseProperties.ky = pop(); + _wizParams.ellipseProperties.kx = pop(); + _wizParams.ellipseProperties.qy = pop(); + _wizParams.ellipseProperties.qx = pop(); + _wizParams.ellipseProperties.py = pop(); + _wizParams.ellipseProperties.px = pop(); break; case 134: _wizParams.processFlags |= kWPFFillColor | kWPFClipBox2; @@ -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/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp index f65d2f6077..f2d92bc2ca 100644 --- a/engines/scumm/he/script_v90he.cpp +++ b/engines/scumm/he/script_v90he.cpp @@ -285,29 +285,29 @@ void ScummEngine_v90he::o90_wizImageOps() { _wizParams.processMode = 13; break; case 142: // HE99+ - _wizParams.field_239D = pop(); - _wizParams.field_2399 = pop(); - _wizParams.field_23A5 = pop(); - _wizParams.field_23A1 = pop(); - copyScriptString(_wizParams.string2, sizeof(_wizParams.string2)); _wizParams.processMode = 15; + _wizParams.fontProperties.bgColor = pop(); + _wizParams.fontProperties.fgColor = pop(); + _wizParams.fontProperties.size = pop(); + _wizParams.fontProperties.style = pop(); + copyScriptString(_wizParams.fontProperties.fontName, sizeof(_wizParams.fontProperties.fontName)); break; case 143: // HE99+ _wizParams.processMode = 16; - _wizParams.field_23AD = pop(); - _wizParams.field_23A9 = pop(); - copyScriptString(_wizParams.string1, sizeof(_wizParams.string1)); + _wizParams.fontProperties.yPos = pop(); + _wizParams.fontProperties.xPos = pop(); + copyScriptString(_wizParams.fontProperties.string, sizeof(_wizParams.fontProperties.string)); break; case 189: // HE99+ _wizParams.processMode = 17; - _wizParams.field_23CD = pop(); - _wizParams.field_23C9 = pop(); - _wizParams.field_23C5 = pop(); - _wizParams.field_23C1 = pop(); - _wizParams.field_23BD = pop(); - _wizParams.field_23B9 = pop(); - _wizParams.field_23B5 = pop(); - _wizParams.field_23B1 = pop(); + _wizParams.ellipseProperties.color = pop(); + _wizParams.ellipseProperties.lod = pop(); + _wizParams.ellipseProperties.ky = pop(); + _wizParams.ellipseProperties.kx = pop(); + _wizParams.ellipseProperties.qy = pop(); + _wizParams.ellipseProperties.qx = pop(); + _wizParams.ellipseProperties.py = pop(); + _wizParams.ellipseProperties.px = pop(); break; case 196: // HE99+ _wizParams.processMode = 14; 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..9a5be1cc5f 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -1422,19 +1422,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 +1456,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 +1571,251 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1; } + 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; + } else { + subConditionBits = 0; + } + + 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: + // 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 +1937,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 +2005,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 +2016,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 +2191,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 +2213,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 +2263,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 +2294,26 @@ 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)); + if (_vm->_game.id == GID_MOONBASE) { + if (params->img.resNum == _vm->_moonbase->_fowSentinelImage && + state == _vm->_moonbase->_fowSentinelState && + params->conditionBits == _vm->_moonbase->_fowSentinelConditionBits) + _vm->_moonbase->renderFOW(0, 0, 0, 0, 0, flags); + } + + drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), params->conditionBits); } } } @@ -2547,6 +2744,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; @@ -2564,6 +2766,18 @@ int Wiz::getWizImageStates(int resNum) { } } +void Wiz::getWizStateSpot(byte *data, int state, int *x, int *y) { + byte *spot = _vm->findWrappedBlock(MKTAG('S','P','O','T'), data, state, 0); + + if (!spot) { + *x = *y = 0; + return; + } + + *x = READ_LE_UINT32(spot + 0x0); + *y = READ_LE_UINT32(spot + 0x4); +} + int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags) { int ret = 0; uint8 *data = _vm->getResourceAddress(rtImage, resNum); @@ -2597,11 +2811,12 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags 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); break; @@ -2641,8 +2856,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 8db438a074..ff5169f7e8 100644 --- a/engines/scumm/he/wiz_he.h +++ b/engines/scumm/he/wiz_he.h @@ -43,10 +43,32 @@ struct WizImage { int state; int flags; int shadow; - int field_390; + int zbuffer; int palette; }; +struct FontProperties { + byte string[4096]; + byte fontName[4096]; + int fgColor; + int bgColor; + int style; + int size; + int xPos; + int yPos; +}; + +struct EllipseProperties { + int px; + int py; + int qx; + int qy; + int kx; + int ky; + int lod; + int color; +}; + struct WizParameters { int field_0; byte filename[260]; @@ -77,27 +99,13 @@ struct WizParameters { int remapNum; int dstResNum; uint16 fillColor; - byte string1[4096]; - byte string2[4096]; - int field_2399; - int field_239D; - int field_23A1; - int field_23A5; - int field_23A9; - int field_23AD; - int field_23B1; - int field_23B5; - int field_23B9; - int field_23BD; - int field_23C1; - int field_23C5; - int field_23C9; - int field_23CD; + FontProperties fontProperties; + EllipseProperties ellipseProperties; Common::Rect box2; - int field_23DE; + int blendFlags; int spriteId; int spriteGroup; - int field_23EA; + int conditionBits; WizImage img; }; @@ -109,6 +117,9 @@ enum WizImageFlags { kWIFMarkBufferDirty = 0x10, kWIFBlitToMemBuffer = 0x20, kWIFIsPolygon = 0x40, + kWIFZPlaneOn = 0x80, + kWIFZPlaneOff = 0x100, + kWIFUseShadow = 0x200, kWIFFlipX = 0x400, kWIFFlipY = 0x800 }; @@ -130,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 { @@ -186,6 +221,8 @@ public: void getWizImageDim(int resNum, int state, int32 &w, int32 &h); int getWizImageStates(int resnum); + int getWizImageStates(const uint8 *ptr); + void getWizStateSpot(byte *data, int state, int *x, int *y); int isWizPixelNonTransparent(int resnum, int state, int x, int y, int flags); uint16 getWizPixelColor(int resnum, int state, int x, int y); int getWizImageData(int resNum, int state, int type); @@ -202,7 +239,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); @@ -210,6 +248,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); 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.cpp b/engines/scumm/scumm.cpp index e7118616ba..ff25dc9201 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -733,7 +733,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 +832,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/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/dialogs.cpp b/engines/tinsel/dialogs.cpp index a84dad942c..4bc28ffb53 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -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/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/design.cpp b/engines/wage/design.cpp index e84cf2e89e..eda28df159 100644 --- a/engines/wage/design.cpp +++ b/engines/wage/design.cpp @@ -45,8 +45,10 @@ * */ +#include "graphics/managed_surface.h" #include "graphics/primitives.h" -#include "wage/wage.h" + +#include "wage/macwindowmanager.h" #include "wage/design.h" namespace Wage { diff --git a/engines/wage/design.h b/engines/wage/design.h index a6e0df4c40..9b0231ca96 100644 --- a/engines/wage/design.h +++ b/engines/wage/design.h @@ -48,10 +48,11 @@ #ifndef WAGE_DESIGN_H #define WAGE_DESIGN_H -#include "graphics/managed_surface.h" #include "common/memstream.h" #include "common/rect.h" +#include "wage/macwindowmanager.h" + namespace Wage { class Design { diff --git a/engines/wage/dialog.cpp b/engines/wage/dialog.cpp index 263570bddc..d9bb3e6a61 100644 --- a/engines/wage/dialog.cpp +++ b/engines/wage/dialog.cpp @@ -49,6 +49,7 @@ #include "common/events.h" #include "wage/wage.h" +#include "wage/macwindowmanager.h" #include "wage/design.h" #include "wage/gui.h" #include "wage/dialog.h" @@ -88,11 +89,11 @@ Dialog::~Dialog() { } const Graphics::Font *Dialog::getDialogFont() { - return _gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); + return _gui->_wm.getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); } void Dialog::paint() { - Design::drawFilledRect(&_gui->_screen, _bbox, kColorWhite, _gui->_patterns, kPatternSolid); + Design::drawFilledRect(&_gui->_screen, _bbox, kColorWhite, _gui->_wm.getPatterns(), kPatternSolid); _font->drawString(&_gui->_screen, _text, _bbox.left + 24, _bbox.top + 16, _bbox.width(), kColorBlack); static int boxOutline[] = { 1, 0, 0, 1, 1 }; @@ -114,7 +115,7 @@ void Dialog::paint() { Common::Rect bb(button->bounds.left + 5, button->bounds.top + 5, button->bounds.right - 5, button->bounds.bottom - 5); - Design::drawFilledRect(&_gui->_screen, bb, kColorBlack, _gui->_patterns, kPatternSolid); + Design::drawFilledRect(&_gui->_screen, bb, kColorBlack, _gui->_wm.getPatterns(), kPatternSolid); color = kColorWhite; } @@ -137,7 +138,7 @@ void Dialog::drawOutline(Common::Rect &bounds, int *spec, int speclen) { for (int i = 0; i < speclen; i++) if (spec[i] != 0) Design::drawRect(&_gui->_screen, bounds.left + i, bounds.top + i, bounds.right - i, bounds.bottom - i, - 1, kColorBlack, _gui->_patterns, kPatternSolid); + 1, kColorBlack, _gui->_wm.getPatterns(), kPatternSolid); } int Dialog::run() { @@ -145,7 +146,7 @@ int Dialog::run() { Common::Rect r(_bbox); _tempSurface.copyRectToSurface(_gui->_screen.getBasePtr(_bbox.left, _bbox.top), _gui->_screen.pitch, 0, 0, _bbox.width() + 1, _bbox.height() + 1); - _gui->pushArrowCursor(); + _gui->_wm.pushArrowCursor(); while (!shouldQuit) { Common::Event event; @@ -189,7 +190,7 @@ int Dialog::run() { _gui->_screen.copyRectToSurface(_tempSurface.getBasePtr(0, 0), _tempSurface.pitch, _bbox.left, _bbox.top, _bbox.width() + 1, _bbox.height() + 1); g_system->copyRectToScreen(_gui->_screen.getBasePtr(r.left, r.top), _gui->_screen.pitch, r.left, r.top, r.width() + 1, r.height() + 1); - _gui->popCursor(); + _gui->_wm.popCursor(); return _pressedButton; } diff --git a/engines/wage/entities.cpp b/engines/wage/entities.cpp index d0a838f1e7..43ac6c8cc7 100644 --- a/engines/wage/entities.cpp +++ b/engines/wage/entities.cpp @@ -52,6 +52,7 @@ #include "wage/world.h" #include "common/memstream.h" +#include "graphics/managed_surface.h" namespace Wage { @@ -138,16 +139,16 @@ void Scene::paint(Graphics::ManagedSurface *surface, int x, int y) { Common::Rect r(x + 5, y + 5, _design->getBounds()->width() + x - 10, _design->getBounds()->height() + y - 10); surface->fillRect(r, kColorWhite); - _design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y); + _design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); for (ObjList::const_iterator it = _objs.begin(); it != _objs.end(); ++it) { debug(2, "paining Obj: %s, index: %d, type: %d", (*it)->_name.c_str(), (*it)->_index, (*it)->_type); - (*it)->_design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y); + (*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); } for (ChrList::const_iterator it = _chrs.begin(); it != _chrs.end(); ++it) { debug(2, "paining Chr: %s", (*it)->_name.c_str()); - (*it)->_design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y); + (*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); } } diff --git a/engines/wage/gui-console.cpp b/engines/wage/gui-console.cpp index ca1917b96d..8b6fe43a17 100644 --- a/engines/wage/gui-console.cpp +++ b/engines/wage/gui-console.cpp @@ -45,6 +45,7 @@ * */ +#include "common/events.h" #include "common/timer.h" #include "common/unzip.h" #include "graphics/cursorman.h" @@ -54,7 +55,8 @@ #include "wage/wage.h" #include "wage/design.h" #include "wage/entities.h" -#include "wage/menu.h" +#include "wage/macwindow.h" +#include "wage/macmenu.h" #include "wage/gui.h" #include "wage/world.h" @@ -66,7 +68,7 @@ const Graphics::Font *Gui::getConsoleFont() { snprintf(fontName, 128, "%s-%d", scene->getFontName(), scene->_fontSize); - return getFont(fontName, Graphics::FontManager::kConsoleFont); + return _wm.getFont(fontName, Graphics::FontManager::kConsoleFont); } void Gui::clearOutput() { @@ -196,7 +198,7 @@ void Gui::renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r) { color = kColorWhite; Common::Rect trect(0, y1, _console.w, y1 + _consoleLineHeight); - Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid); + Design::drawFilledRect(&_console, trect, kColorBlack, _wm.getPatterns(), kPatternSolid); } if (line == _selectionStartY || line == _selectionEndY) { @@ -223,7 +225,7 @@ void Gui::renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r) { else trect.left = rectW; - Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid); + Design::drawFilledRect(&_console, trect, kColorBlack, _wm.getPatterns(), kPatternSolid); font->drawString(&_console, beg, x1, y1, textW, color1); font->drawString(&_console, end, x1 + rectW - kConWPadding - kConWOverlap, y1, textW, color2); @@ -242,7 +244,7 @@ void Gui::renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r) { int rectW2 = rectW1 + font->getStringWidth(mid); Common::Rect trect(rectW1, y1, rectW2, y1 + _consoleLineHeight); - Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid); + Design::drawFilledRect(&_console, trect, kColorBlack, _wm.getPatterns(), kPatternSolid); font->drawString(&_console, beg, x1, y1, textW, kColorBlack); font->drawString(&_console, mid, x1 + rectW1 - kConWPadding - kConWOverlap, y1, textW, kColorWhite); @@ -422,4 +424,140 @@ void Gui::enableNewGameMenus() { _menu->enableCommand(kMenuFile, kMenuActionQuit, true); } +bool Gui::processConsoleEvents(WindowClick click, Common::Event &event) { + if (click == kBorderScrollUp || click == kBorderScrollDown) { + if (event.type == Common::EVENT_LBUTTONDOWN) { + int consoleHeight = _consoleWindow->getInnerDimensions().height(); + int textFullSize = _lines.size() * _consoleLineHeight + consoleHeight; + float scrollPos = (float)_scrollPos / textFullSize; + float scrollSize = (float)consoleHeight / textFullSize; + + _consoleWindow->setScroll(scrollPos, scrollSize); + + return true; + } else if (event.type == Common::EVENT_LBUTTONUP) { + int oldScrollPos = _scrollPos; + + switch (click) { + case kBorderScrollUp: + _scrollPos = MAX<int>(0, _scrollPos - _consoleLineHeight); + undrawCursor(); + _cursorY -= (_scrollPos - oldScrollPos); + _consoleDirty = true; + _consoleFullRedraw = true; + break; + case kBorderScrollDown: + _scrollPos = MIN<int>((_lines.size() - 2) * _consoleLineHeight, _scrollPos + _consoleLineHeight); + undrawCursor(); + _cursorY -= (_scrollPos - oldScrollPos); + _consoleDirty = true; + _consoleFullRedraw = true; + break; + default: + return false; + } + + return true; + } + + return false; + } + + if (click == kBorderResizeButton) { + _consoleDirty = true; + _consoleFullRedraw = true; + + return true; + } + + if (click == kBorderInner) { + if (event.type == Common::EVENT_LBUTTONDOWN) { + startMarking(event.mouse.x, event.mouse.y); + + return true; + } else if (event.type == Common::EVENT_LBUTTONUP) { + if (_inTextSelection) { + _inTextSelection = false; + + if (_selectionEndY == -1 || + (_selectionEndX == _selectionStartX && _selectionEndY == _selectionStartY)) { + _selectionStartY = _selectionEndY = -1; + _consoleFullRedraw = true; + _menu->enableCommand(kMenuEdit, kMenuActionCopy, false); + } else { + _menu->enableCommand(kMenuEdit, kMenuActionCopy, true); + + bool cutAllowed = false; + + if (_selectionStartY == _selectionEndY && _selectionStartY == (int)_lines.size() - 1) + cutAllowed = true; + + _menu->enableCommand(kMenuEdit, kMenuActionCut, cutAllowed); + _menu->enableCommand(kMenuEdit, kMenuActionClear, cutAllowed); + } + } + + return true; + } else if (event.type == Common::EVENT_MOUSEMOVE) { + if (_inTextSelection) { + updateTextSelection(event.mouse.x, event.mouse.y); + return true; + } + } + + return false; + } + + return false; +} + +int Gui::calcTextX(int x, int textLine) { + const Graphics::Font *font = getConsoleFont(); + + if ((uint)textLine >= _lines.size()) + return 0; + + Common::String str = _lines[textLine]; + + x -= _consoleWindow->getInnerDimensions().left; + + for (int i = str.size(); i >= 0; i--) { + if (font->getStringWidth(str) < x) { + return i; + } + + str.deleteLastChar(); + } + + return 0; +} + +int Gui::calcTextY(int y) { + y -= _consoleWindow->getInnerDimensions().top; + + if (y < 0) + y = 0; + + const int firstLine = _scrollPos / _consoleLineHeight; + int textLine = (y - _scrollPos % _consoleLineHeight) / _consoleLineHeight + firstLine; + + return textLine; +} + +void Gui::startMarking(int x, int y) { + _selectionStartY = calcTextY(y); + _selectionStartX = calcTextX(x, _selectionStartY); + + _selectionEndY = -1; + + _inTextSelection = true; +} + +void Gui::updateTextSelection(int x, int y) { + _selectionEndY = calcTextY(y); + _selectionEndX = calcTextX(x, _selectionEndY); + + _consoleFullRedraw = true; +} + } // End of namespace Wage diff --git a/engines/wage/gui.cpp b/engines/wage/gui.cpp index 2841013a26..310e5734b7 100644 --- a/engines/wage/gui.cpp +++ b/engines/wage/gui.cpp @@ -46,10 +46,8 @@ */ #include "common/timer.h" -#include "common/unzip.h" +#include "common/system.h" #include "graphics/cursorman.h" -#include "graphics/fonts/bdf.h" -#include "graphics/palette.h" #include "graphics/primitives.h" #include "wage/wage.h" @@ -58,60 +56,30 @@ #include "wage/gui.h" #include "wage/macwindow.h" #include "wage/macwindowmanager.h" -#include "wage/menu.h" +#include "wage/macmenu.h" #include "wage/world.h" namespace Wage { -static const byte palette[] = { - 0, 0, 0, // Black - 0x80, 0x80, 0x80, // Gray - 0xff, 0xff, 0xff, // White - 0x00, 0xff, 0x00, // Green - 0x00, 0xcf, 0x00 // Green2 -}; - -static byte fillPatterns[][8] = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, // kPatternSolid - { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, // kPatternStripes - { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa } // kPatternCheckers2 -}; - -static const byte macCursorArrow[] = { - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, - 2, 0, 0, 0, 2, 3, 3, 3, 3, 3, 3, - 2, 0, 0, 0, 0, 2, 3, 3, 3, 3, 3, - 2, 0, 0, 0, 0, 0, 2, 3, 3, 3, 3, - 2, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, - 2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, - 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, - 2, 0, 0, 2, 0, 0, 2, 3, 3, 3, 3, - 2, 0, 2, 3, 2, 0, 0, 2, 3, 3, 3, - 2, 2, 3, 3, 2, 0, 0, 2, 3, 3, 3, - 2, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, - 3, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, - 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3 -}; - -static const byte macCursorBeam[] = { - 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, - 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, - 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, +static const MenuData menuSubItems[] = { + { kMenuHighLevel, "File", 0, 0, false }, + { kMenuHighLevel, "Edit", 0, 0, false }, + { kMenuFile, "New", kMenuActionNew, 0, false }, + { kMenuFile, "Open...", kMenuActionOpen, 0, false }, + { kMenuFile, "Close", kMenuActionClose, 0, true }, + { kMenuFile, "Save", kMenuActionSave, 0, false }, + { kMenuFile, "Save as...", kMenuActionSaveAs, 0, true }, + { kMenuFile, "Revert", kMenuActionRevert, 0, false }, + { kMenuFile, "Quit", kMenuActionQuit, 0, true }, + + { kMenuEdit, "Undo", kMenuActionUndo, 'Z', false }, + { kMenuEdit, NULL, 0, 0, false }, + { kMenuEdit, "Cut", kMenuActionCut, 'K', false }, + { kMenuEdit, "Copy", kMenuActionCopy, 'C', false }, + { kMenuEdit, "Paste", kMenuActionPaste, 'V', false }, + { kMenuEdit, "Clear", kMenuActionClear, 'B', false }, + + { 0, NULL, 0, 0, false } }; static void cursorTimerHandler(void *refCon) { @@ -144,13 +112,14 @@ static void cursorTimerHandler(void *refCon) { static bool sceneWindowCallback(WindowClick click, Common::Event &event, void *gui); static bool consoleWindowCallback(WindowClick click, Common::Event &event, void *gui); +static void menuCommandsCallback(int action, Common::String &text, void *data); + Gui::Gui(WageEngine *engine) { _engine = engine; _scene = NULL; _sceneDirty = true; _consoleDirty = true; - _menuDirty = true; _cursorDirty = false; _consoleFullRedraw = true; _screen.create(g_system->getWidth(), g_system->getHeight(), Graphics::PixelFormat::createFormatCLUT8()); @@ -160,7 +129,6 @@ Gui::Gui(WageEngine *engine) { _scrollPos = 0; _consoleLineHeight = 8; // Dummy value which makes sense _consoleNumLines = 24; // Dummy value - _builtInFonts = false; _cursorX = 0; _cursorY = 0; @@ -173,26 +141,32 @@ Gui::Gui(WageEngine *engine) { _inputTextLineNum = 0; - g_system->getPaletteManager()->setPalette(palette, 0, ARRAYSIZE(palette) / 3); + g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "wageCursor"); - CursorMan.replaceCursorPalette(palette, 0, 4); - CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); - _cursorIsArrow = true; - CursorMan.showMouse(true); + _menu = _wm.addMenu(); - for (int i = 0; i < ARRAYSIZE(fillPatterns); i++) - _patterns.push_back(fillPatterns[i]); + _menu->setCommandsCallback(menuCommandsCallback, this); - loadFonts(); + _menu->addStaticMenus(menuSubItems); + _menu->addMenuSubItem(kMenuAbout, _engine->_world->getAboutMenuItemName(), kMenuActionAbout); - g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "wageCursor"); + _commandsMenuId = _menu->addMenuItem(_engine->_world->_commandsMenuName.c_str()); + regenCommandsMenu(); + + if (!_engine->_world->_weaponMenuDisabled) { + _weaponsMenuId = _menu->addMenuItem(_engine->_world->_weaponsMenuName.c_str()); - _menu = new Menu(this); + regenWeaponsMenu(); + } else { + _weaponsMenuId = -1; + } + + _menu->calcDimensions(); - _sceneWindow = _wm.addWindow(false, false); + _sceneWindow = _wm.addWindow(false, false, false); _sceneWindow->setCallback(sceneWindowCallback, this); - _consoleWindow = _wm.addWindow(true, true); + _consoleWindow = _wm.addWindow(true, true, true); _consoleWindow->setCallback(consoleWindowCallback, this); } @@ -200,7 +174,6 @@ Gui::~Gui() { _screen.free(); _console.free(); g_system->getTimerManager()->removeTimerProc(&cursorTimerHandler); - delete _menu; } void Gui::undrawCursor() { @@ -210,35 +183,9 @@ void Gui::undrawCursor() { _cursorOff = false; } -const Graphics::Font *Gui::getFont(const char *name, Graphics::FontManager::FontUsage fallback) { - const Graphics::Font *font = 0; - - if (!_builtInFonts) { - font = FontMan.getFontByName(name); - - if (!font) - warning("Cannot load font %s", name); - } - - if (_builtInFonts || !font) - font = FontMan.getFontByUsage(fallback); - - return font; -} - -const Graphics::Font *Gui::getTitleFont() { - return getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); -} - void Gui::draw() { if (_engine->_isGameOver) { - if (_menuDirty) { - _wm.setFullRefresh(true); - _wm.draw(); - _menu->render(); - } - - _menuDirty = false; + _wm.draw(); return; } @@ -263,10 +210,7 @@ void Gui::draw() { _wm.draw(); - if (_menuDirty) - _menu->render(); - - if (_cursorDirty) { + if (_cursorDirty && _cursorRect.left < _screen.w && _cursorRect.bottom < _screen.h) { g_system->copyRectToScreen(_screen.getBasePtr(_cursorRect.left, _cursorRect.top), _screen.pitch, _cursorRect.left, _cursorRect.top, _cursorRect.width(), _cursorRect.height()); @@ -275,7 +219,6 @@ void Gui::draw() { _sceneDirty = false; _consoleDirty = false; - _menuDirty = false; _consoleFullRedraw = false; } @@ -288,7 +231,7 @@ void Gui::drawScene() { _sceneDirty = true; _consoleDirty = true; - _menuDirty = true; + _menu->setDirty(true); _consoleFullRedraw = true; } @@ -299,11 +242,6 @@ static bool sceneWindowCallback(WindowClick click, Common::Event &event, void *g } bool Gui::processSceneEvents(WindowClick click, Common::Event &event) { - if (_cursorIsArrow == false) { - CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); - _cursorIsArrow = true; - } - if (click == kBorderInner && event.type == Common::EVENT_LBUTTONUP) { Designed *obj = _scene->lookUpEntity(event.mouse.x - _sceneWindow->getDimensions().left, event.mouse.y - _sceneWindow->getDimensions().top); @@ -333,265 +271,89 @@ static bool consoleWindowCallback(WindowClick click, Common::Event &event, void return gui->processConsoleEvents(click, event); } -bool Gui::processConsoleEvents(WindowClick click, Common::Event &event) { - if (click != kBorderInner && _cursorIsArrow == false) { - CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); - _cursorIsArrow = true; - } - - if (click == kBorderScrollUp || click == kBorderScrollDown) { - if (event.type == Common::EVENT_LBUTTONDOWN) { - int consoleHeight = _consoleWindow->getInnerDimensions().height(); - int textFullSize = _lines.size() * _consoleLineHeight + consoleHeight; - float scrollPos = (float)_scrollPos / textFullSize; - float scrollSize = (float)consoleHeight / textFullSize; - - _consoleWindow->setScroll(scrollPos, scrollSize); - - return true; - } else if (event.type == Common::EVENT_LBUTTONUP) { - int oldScrollPos = _scrollPos; - - switch (click) { - case kBorderScrollUp: - _scrollPos = MAX<int>(0, _scrollPos - _consoleLineHeight); - undrawCursor(); - _cursorY -= (_scrollPos - oldScrollPos); - _consoleDirty = true; - _consoleFullRedraw = true; - break; - case kBorderScrollDown: - _scrollPos = MIN<int>((_lines.size() - 2) * _consoleLineHeight, _scrollPos + _consoleLineHeight); - undrawCursor(); - _cursorY -= (_scrollPos - oldScrollPos); - _consoleDirty = true; - _consoleFullRedraw = true; - break; - default: - return false; - } - - return true; - } - - return false; - } - - if (click == kBorderResizeButton) { - _consoleDirty = true; - _consoleFullRedraw = true; - - return true; - } - - if (click == kBorderInner) { - if (event.type == Common::EVENT_LBUTTONDOWN) { - startMarking(event.mouse.x, event.mouse.y); - - return true; - } else if (event.type == Common::EVENT_LBUTTONUP) { - if (_inTextSelection) { - _inTextSelection = false; - - if (_selectionEndY == -1 || - (_selectionEndX == _selectionStartX && _selectionEndY == _selectionStartY)) { - _selectionStartY = _selectionEndY = -1; - _consoleFullRedraw = true; - _menu->enableCommand(kMenuEdit, kMenuActionCopy, false); - } else { - _menu->enableCommand(kMenuEdit, kMenuActionCopy, true); - - bool cutAllowed = false; - - if (_selectionStartY == _selectionEndY && _selectionStartY == (int)_lines.size() - 1) - cutAllowed = true; - - _menu->enableCommand(kMenuEdit, kMenuActionCut, cutAllowed); - _menu->enableCommand(kMenuEdit, kMenuActionClear, cutAllowed); - } - } - - return true; - } else if (event.type == Common::EVENT_MOUSEMOVE) { - if (_inTextSelection) { - updateTextSelection(event.mouse.x, event.mouse.y); - return true; - } - - if (_cursorIsArrow) { - CursorMan.replaceCursor(macCursorBeam, 11, 16, 3, 8, 3); - _cursorIsArrow = false; - } - } - - return false; - } - - return false; +//////////////// +// Menu stuff +//////////////// +void Gui::regenCommandsMenu() { + _menu->createSubMenuFromString(_commandsMenuId, _engine->_world->_commandsMenu.c_str()); } -void Gui::loadFonts() { - Common::Archive *dat; - - dat = Common::makeZipArchive("wage.dat"); - - if (!dat) { - warning("Could not find wage.dat. Falling back to built-in fonts"); - _builtInFonts = true; - +void Gui::regenWeaponsMenu() { + if (_engine->_world->_weaponMenuDisabled) return; - } - Common::ArchiveMemberList list; - dat->listMembers(list); + _menu->clearSubMenu(_weaponsMenuId); - for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { - Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName()); + Chr *player = _engine->_world->_player; + ObjArray *weapons = player->getWeapons(true); - Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream); + bool empty = true; - delete stream; + for (uint i = 0; i < weapons->size(); i++) { + Obj *obj = (*weapons)[i]; + if (obj->_type == Obj::REGULAR_WEAPON || + obj->_type == Obj::THROW_WEAPON || + obj->_type == Obj::MAGICAL_OBJECT) { + Common::String command(obj->_operativeVerb); + command += " "; + command += obj->_name; - Common::String fontName = (*it)->getName(); + _menu->addMenuSubItem(_weaponsMenuId, command.c_str(), kMenuActionCommand, 0, 0, true); - // Trim the .bdf extension - for (int i = fontName.size() - 1; i >= 0; --i) { - if (fontName[i] == '.') { - while ((uint)i < fontName.size()) { - fontName.deleteLastChar(); - } - break; - } + empty = false; } - - FontMan.assignFontToName(fontName, font); - - debug(2, " %s", fontName.c_str()); } + delete weapons; - _builtInFonts = false; - - delete dat; + if (empty) + _menu->addMenuSubItem(_weaponsMenuId, "You have no weapons", 0, 0, 0, false); } -void Gui::regenCommandsMenu() { - _menu->regenCommandsMenu(); -} - -void Gui::regenWeaponsMenu() { - _menu->regenWeaponsMenu(); -} - -void Gui::processMenuShortCut(byte flags, uint16 ascii) { - _menu->processMenuShortCut(flags, ascii); -} - -void Gui::mouseMove(int x, int y) { - if (_menu->_menuActivated) { - if (_menu->mouseMove(x, y)) - _menuDirty = true; - - return; - } +bool Gui::processEvent(Common::Event &event) { + return _wm.processEvent(event); } -void Gui::pushArrowCursor() { - CursorMan.pushCursor(macCursorArrow, 11, 16, 1, 1, 3); -} +void menuCommandsCallback(int action, Common::String &text, void *data) { + Gui *g = (Gui *)data; -void Gui::popCursor() { - CursorMan.popCursor(); + g->executeMenuCommand(action, text); } -bool Gui::processEvent(Common::Event &event) { - if (_wm.processEvent(event)) - return true; - - switch (event.type) { - case Common::EVENT_MOUSEMOVE: - mouseMove(event.mouse.x, event.mouse.y); +void Gui::executeMenuCommand(int action, Common::String &text) { + switch(action) { + case kMenuActionAbout: + case kMenuActionNew: + case kMenuActionOpen: + case kMenuActionClose: + case kMenuActionSave: + case kMenuActionSaveAs: + case kMenuActionRevert: + case kMenuActionQuit: + + case kMenuActionUndo: + actionUndo(); break; - case Common::EVENT_LBUTTONDOWN: - mouseDown(event.mouse.x, event.mouse.y); + case kMenuActionCut: + actionCut(); break; - case Common::EVENT_LBUTTONUP: - mouseUp(event.mouse.x, event.mouse.y); + case kMenuActionCopy: + actionCopy(); + break; + case kMenuActionPaste: + actionPaste(); + break; + case kMenuActionClear: + actionClear(); break; - default: - return false; - } - - return true; -} - -void Gui::mouseUp(int x, int y) { - if (_menu->_menuActivated) { - if (_menu->mouseRelease(x, y)) { - _sceneDirty = true; - _consoleDirty = true; - _menuDirty = true; - } - - return; - } - - return; -} - -void Gui::mouseDown(int x, int y) { - if (_menu->mouseClick(x, y)) { - _menuDirty = true; - } -} - -int Gui::calcTextX(int x, int textLine) { - const Graphics::Font *font = getConsoleFont(); - - if ((uint)textLine >= _lines.size()) - return 0; - - Common::String str = _lines[textLine]; - - x -= _consoleWindow->getInnerDimensions().left; + case kMenuActionCommand: + _engine->processTurn(&text, NULL); + break; - for (int i = str.size(); i >= 0; i--) { - if (font->getStringWidth(str) < x) { - return i; - } + default: + warning("Unknown action: %d", action); - str.deleteLastChar(); } - - return 0; -} - -int Gui::calcTextY(int y) { - y -= _consoleWindow->getInnerDimensions().top; - - if (y < 0) - y = 0; - - const int firstLine = _scrollPos / _consoleLineHeight; - int textLine = (y - _scrollPos % _consoleLineHeight) / _consoleLineHeight + firstLine; - - return textLine; -} - -void Gui::startMarking(int x, int y) { - _selectionStartY = calcTextY(y); - _selectionStartX = calcTextX(x, _selectionStartY); - - _selectionEndY = -1; - - _inTextSelection = true; -} - -void Gui::updateTextSelection(int x, int y) { - _selectionEndY = calcTextY(y); - _selectionEndX = calcTextX(x, _selectionEndY); - - _consoleFullRedraw = true; } } // End of namespace Wage diff --git a/engines/wage/gui.h b/engines/wage/gui.h index 2feb259e9f..ba1bb5ef3b 100644 --- a/engines/wage/gui.h +++ b/engines/wage/gui.h @@ -50,7 +50,6 @@ #include "common/str-array.h" #include "graphics/font.h" -#include "graphics/fontman.h" #include "graphics/managed_surface.h" #include "common/events.h" #include "common/rect.h" @@ -61,26 +60,13 @@ namespace Wage { class Menu; +class Scene; +class WageEngine; enum { - kMenuHeight = 20, - kMenuLeftMargin = 7, - kMenuSpacing = 13, - kMenuPadding = 16, - kMenuDropdownPadding = 14, - kMenuDropdownItemHeight = 16, - kMenuItemHeight = 20, - kDesktopArc = 7, - kComponentsPadding = 10, kCursorHeight = 12 }; -enum { - kPatternSolid = 1, - kPatternStripes = 2, - kPatternCheckers2 = 3 -}; - class Gui { public: Gui(WageEngine *engine); @@ -90,17 +76,11 @@ public: void appendText(const char *str); void clearOutput(); bool processEvent(Common::Event &event); - void mouseMove(int x, int y); - void mouseDown(int x, int y); - void mouseUp(int x, int y); + void drawInput(); void setSceneDirty() { _sceneDirty = true; } - const Graphics::Font *getFont(const char *name, Graphics::FontManager::FontUsage fallback); void regenCommandsMenu(); void regenWeaponsMenu(); - void processMenuShortCut(byte flags, uint16 ascii); - void pushArrowCursor(); - void popCursor(); void actionCopy(); void actionPaste(); @@ -111,19 +91,15 @@ public: void disableAllMenus(); void enableNewGameMenus(); - bool builtInFonts() { return _builtInFonts; } - bool processSceneEvents(WindowClick click, Common::Event &event); bool processConsoleEvents(WindowClick click, Common::Event &event); - - Patterns &getPatterns() { return _patterns; } + void executeMenuCommand(int action, Common::String &text); private: void drawScene(); void drawConsole(); void undrawCursor(); void renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r); - void loadFonts(); void flowText(Common::String &str); const Graphics::Font *getConsoleFont(); const Graphics::Font *getTitleFont(); @@ -137,17 +113,12 @@ public: int _cursorX, _cursorY; bool _cursorState; - bool _builtInFonts; WageEngine *_engine; - Patterns _patterns; - bool _cursorDirty; Common::Rect _cursorRect; bool _cursorOff; - bool _menuDirty; - Scene *_scene; MacWindowManager _wm; @@ -167,8 +138,6 @@ private: uint _consoleNumLines; bool _consoleFullRedraw; - bool _cursorIsArrow; - bool _inTextSelection; int _selectionStartX; int _selectionStartY; @@ -179,6 +148,9 @@ private: Common::String _undobuffer; int _inputTextLineNum; + + int _commandsMenuId; + int _weaponsMenuId; }; } // End of namespace Wage diff --git a/engines/wage/menu.cpp b/engines/wage/macmenu.cpp index 27cbf5e4f5..ed5f5070ff 100644 --- a/engines/wage/menu.cpp +++ b/engines/wage/macmenu.cpp @@ -48,15 +48,25 @@ #include "common/system.h" #include "common/keyboard.h" -#include "wage/wage.h" -#include "wage/entities.h" -#include "wage/design.h" -#include "wage/gui.h" -#include "wage/menu.h" -#include "wage/world.h" +#include "graphics/primitives.h" +#include "graphics/font.h" + +#include "wage/macwindowmanager.h" +#include "wage/macwindow.h" +#include "wage/macmenu.h" namespace Wage { +enum { + kMenuHeight = 20, + kMenuLeftMargin = 7, + kMenuSpacing = 13, + kMenuPadding = 16, + kMenuDropdownPadding = 14, + kMenuDropdownItemHeight = 16, + kMenuItemHeight = 20 +}; + struct MenuSubItem { Common::String text; int action; @@ -79,66 +89,65 @@ struct MenuItem { MenuItem(const char *n) : name(n) {} }; -struct MenuData { - int menunum; - const char *title; - int action; - byte shortcut; - bool enabled; -} static const menuSubItems[] = { - { kMenuFile, "New", kMenuActionNew, 0, false }, - { kMenuFile, "Open...", kMenuActionOpen, 0, false }, - { kMenuFile, "Close", kMenuActionClose, 0, true }, - { kMenuFile, "Save", kMenuActionSave, 0, false }, - { kMenuFile, "Save as...", kMenuActionSaveAs, 0, true }, - { kMenuFile, "Revert", kMenuActionRevert, 0, false }, - { kMenuFile, "Quit", kMenuActionQuit, 0, true }, - - { kMenuEdit, "Undo", kMenuActionUndo, 'Z', false }, - { kMenuEdit, NULL, 0, 0, false }, - { kMenuEdit, "Cut", kMenuActionCut, 'K', false }, - { kMenuEdit, "Copy", kMenuActionCopy, 'C', false }, - { kMenuEdit, "Paste", kMenuActionPaste, 'V', false }, - { kMenuEdit, "Clear", kMenuActionClear, 'B', false }, - - { 0, NULL, 0, 0, false } -}; +Menu::Menu(int id, const Common::Rect &bounds, MacWindowManager *wm) + : BaseMacWindow(id, false, wm) { + _font = getMenuFont(); -Menu::Menu(Gui *gui) : _gui(gui) { - assert(_gui->_engine); - assert(_gui->_engine->_world); + _screen.create(bounds.width(), bounds.height(), Graphics::PixelFormat::createFormatCLUT8()); - _font = getMenuFont(); + _bbox.left = 0; + _bbox.top = 0; + _bbox.right = _screen.w; + _bbox.bottom = kMenuHeight; + + _menuActivated = false; + _activeItem = -1; + _activeSubItem = -1; + + _ccallback = NULL; + _cdata = NULL; + + _tempSurface.create(_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8()); +} + +Menu::~Menu() { + for (uint i = 0; i < _items.size(); i++) { + for (uint j = 0; j < _items[i]->subitems.size(); j++) + delete _items[i]->subitems[j]; + delete _items[i]; + } +} - MenuItem *about = new MenuItem(_gui->_builtInFonts ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple +void Menu::addStaticMenus(const MenuData *data) { + MenuItem *about = new MenuItem(_wm->hasBuiltInFonts() ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple _items.push_back(about); - _items[0]->subitems.push_back(new MenuSubItem(_gui->_engine->_world->getAboutMenuItemName(), kMenuActionAbout)); - MenuItem *file = new MenuItem("File"); - _items.push_back(file); + for (int i = 0; data[i].menunum; i++) { + const MenuData *m = &data[i]; - MenuItem *edit = new MenuItem("Edit"); - _items.push_back(edit); + if (m->menunum == kMenuHighLevel) { + MenuItem *item = new MenuItem(m->title); + _items.push_back(item); - for (int i = 0; menuSubItems[i].menunum; i++) { - const MenuData *m = &menuSubItems[i]; + continue; + } _items[m->menunum]->subitems.push_back(new MenuSubItem(m->title, m->action, 0, m->shortcut, m->enabled)); } +} - _commands = new MenuItem(_gui->_engine->_world->_commandsMenuName.c_str()); - _items.push_back(_commands); - regenCommandsMenu(); - - _weapons = NULL; +int Menu::addMenuItem(const char *name) { + MenuItem *i = new MenuItem(name); + _items.push_back(i); - if (!_gui->_engine->_world->_weaponMenuDisabled) { - _weapons = new MenuItem(_gui->_engine->_world->_weaponsMenuName.c_str()); - _items.push_back(_weapons); + return _items.size() - 1; +} - regenWeaponsMenu(); - } +void Menu::addMenuSubItem(int id, const char *text, int action, int style, char shortcut, bool enabled) { + _items[id]->subitems.push_back(new MenuSubItem(text, action, style, shortcut, enabled)); +} +void Menu::calcDimensions() { // Calculate menu dimensions int y = 1; int x = 18; @@ -150,47 +159,29 @@ Menu::Menu(Gui *gui) : _gui(gui) { _items[i]->bbox.left = x - kMenuLeftMargin; _items[i]->bbox.top = y; _items[i]->bbox.right = x + w + kMenuSpacing - kMenuLeftMargin; - _items[i]->bbox.bottom = y + _font->getFontHeight() + (_gui->_builtInFonts ? 3 : 2); + _items[i]->bbox.bottom = y + _font->getFontHeight() + (_wm->hasBuiltInFonts() ? 3 : 2); } calcMenuBounds(_items[i]); x += w + kMenuSpacing; } - - _bbox.left = 0; - _bbox.top = 0; - _bbox.right = _gui->_screen.w - 1; - _bbox.bottom = kMenuHeight - 1; - - _menuActivated = false; - _activeItem = -1; - _activeSubItem = -1; - - _screenCopy.create(_gui->_screen.w, _gui->_screen.h, Graphics::PixelFormat::createFormatCLUT8()); - _tempSurface.create(_gui->_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8()); -} - -Menu::~Menu() { - for (uint i = 0; i < _items.size(); i++) { - for (uint j = 0; j < _items[i]->subitems.size(); j++) - delete _items[i]->subitems[j]; - delete _items[i]; - } } -void Menu::regenCommandsMenu() { - for (uint j = 0; j < _commands->subitems.size(); j++) - delete _commands->subitems[j]; +void Menu::clearSubMenu(int id) { + MenuItem *menu = _items[id]; - _commands->subitems.clear(); + for (uint j = 0; j < menu->subitems.size(); j++) + delete menu->subitems[j]; - createCommandsMenu(_commands); - calcMenuBounds(_commands); + menu->subitems.clear(); } -void Menu::createCommandsMenu(MenuItem *menu) { - Common::String string(_gui->_engine->_world->_commandsMenu); +void Menu::createSubMenuFromString(int id, const char *str) { + clearSubMenu(id); + + MenuItem *menu = _items[id]; + Common::String string(str); Common::String item; @@ -253,45 +244,12 @@ void Menu::createCommandsMenu(MenuItem *menu) { item.clear(); } -} - -void Menu::regenWeaponsMenu() { - if (_gui->_engine->_world->_weaponMenuDisabled) - return; - - for (uint j = 0; j < _weapons->subitems.size(); j++) - delete _weapons->subitems[j]; - - _weapons->subitems.clear(); - - createWeaponsMenu(_weapons); - calcMenuBounds(_weapons); -} - -void Menu::createWeaponsMenu(MenuItem *menu) { - Chr *player = _gui->_engine->_world->_player; - ObjArray *weapons = player->getWeapons(true); - - for (uint i = 0; i < weapons->size(); i++) { - Obj *obj = (*weapons)[i]; - if (obj->_type == Obj::REGULAR_WEAPON || - obj->_type == Obj::THROW_WEAPON || - obj->_type == Obj::MAGICAL_OBJECT) { - Common::String command(obj->_operativeVerb); - command += " "; - command += obj->_name; - - menu->subitems.push_back(new MenuSubItem(command.c_str(), kMenuActionCommand, 0, 0, true)); - } - } - delete weapons; - if (menu->subitems.empty()) - menu->subitems.push_back(new MenuSubItem("You have no weapons", 0, 0, 0, false)); + calcMenuBounds(menu); } const Graphics::Font *Menu::getMenuFont() { - return _gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); + return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); } const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) { @@ -299,7 +257,7 @@ const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) { *res = 0; if (item->shortcut != 0) - sprintf(res, "%s%c%c", prefix, (_gui->_builtInFonts ? '^' : '\x11'), item->shortcut); + sprintf(res, "%s%c%c", prefix, (_wm->hasBuiltInFonts() ? '^' : '\x11'), item->shortcut); return res; } @@ -338,14 +296,35 @@ void Menu::calcMenuBounds(MenuItem *menu) { menu->subbbox.bottom = y2; } -void Menu::render() { +static void drawPixelPlain(int x, int y, int color, void *data) { + Graphics::ManagedSurface *surface = (Graphics::ManagedSurface *)data; + + if (x >= 0 && x < surface->w && y >= 0 && y < surface->h) + *((byte *)surface->getBasePtr(x, y)) = (byte)color; +} + +static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color) { + Graphics::drawRoundRect(rect, arc, color, true, drawPixelPlain, surface); +} + +bool Menu::draw(Graphics::ManagedSurface *g, bool forceRedraw) { Common::Rect r(_bbox); - Design::drawFilledRoundRect(&_gui->_screen, r, kDesktopArc, kColorWhite, _gui->_patterns, kPatternSolid); + if (!_contentIsDirty && !forceRedraw) + return false; + + _contentIsDirty = false; + + _screen.clear(kColorGreen); + + drawFilledRoundRect(&_screen, r, kDesktopArc, kColorWhite); r.top = 7; - Design::drawFilledRect(&_gui->_screen, r, kColorWhite, _gui->_patterns, kPatternSolid); + _screen.fillRect(r, kColorWhite); r.top = kMenuHeight - 1; - Design::drawFilledRect(&_gui->_screen, r, kColorBlack, _gui->_patterns, kPatternSolid); + r.bottom++; + _screen.fillRect(r, kColorGreen); + r.bottom--; + _screen.fillRect(r, kColorBlack); for (uint i = 0; i < _items.size(); i++) { int color = kColorBlack; @@ -355,19 +334,24 @@ void Menu::render() { Common::Rect hbox = it->bbox; hbox.left -= 1; - hbox.right += 2; + hbox.right += 3; + hbox.bottom += 1; - Design::drawFilledRect(&_gui->_screen, hbox, kColorBlack, _gui->_patterns, kPatternSolid); + _screen.fillRect(hbox, kColorBlack); color = kColorWhite; if (!it->subitems.empty()) renderSubmenu(it); } - _font->drawString(&_gui->_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_gui->_builtInFonts ? 2 : 1), it->bbox.width(), color); + _font->drawString(&_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_wm->hasBuiltInFonts() ? 2 : 1), it->bbox.width(), color); } - g_system->copyRectToScreen(_gui->_screen.getPixels(), _gui->_screen.pitch, 0, 0, _gui->_screen.w, kMenuHeight); + g->transBlitFrom(_screen, kColorGreen); + + g_system->copyRectToScreen(g->getPixels(), g->pitch, 0, 0, g->w, g->h); + + return true; } void Menu::renderSubmenu(MenuItem *menu) { @@ -376,10 +360,12 @@ void Menu::renderSubmenu(MenuItem *menu) { if (r->width() == 0 || r->height() == 0) return; - Design::drawFilledRect(&_gui->_screen, *r, kColorWhite, _gui->_patterns, kPatternSolid); - Design::drawRect(&_gui->_screen, *r, 1, kColorBlack, _gui->_patterns, kPatternSolid); - Design::drawVLine(&_gui->_screen, r->right + 1, r->top + 3, r->bottom + 1, 1, kColorBlack, _gui->_patterns, kPatternSolid); - Design::drawHLine(&_gui->_screen, r->left + 3, r->right + 1, r->bottom + 1, 1, kColorBlack, _gui->_patterns, kPatternSolid); + _screen.fillRect(*r, kColorWhite); + _screen.frameRect(*r, kColorBlack); + _screen.vLine(r->right, r->top + 3, r->bottom + 1, kColorBlack); + _screen.vLine(r->right + 1, r->top + 3, r->bottom + 1, kColorBlack); + _screen.hLine(r->left + 3, r->bottom, r->right + 1, kColorBlack); + _screen.hLine(r->left + 3, r->bottom + 1, r->right + 1, kColorBlack); int x = r->left + kMenuDropdownPadding; int y = r->top + 1; @@ -391,13 +377,13 @@ void Menu::renderSubmenu(MenuItem *menu) { int color = kColorBlack; if (i == (uint)_activeSubItem && !text.empty() && menu->subitems[i]->enabled) { color = kColorWhite; - Common::Rect trect(r->left, y - (_gui->_builtInFonts ? 1 : 0), r->right, y + _font->getFontHeight()); + Common::Rect trect(r->left, y - (_wm->hasBuiltInFonts() ? 1 : 0), r->right, y + _font->getFontHeight()); - Design::drawFilledRect(&_gui->_screen, trect, kColorBlack, _gui->_patterns, kPatternSolid); + _screen.fillRect(trect, kColorBlack); } if (!text.empty()) { - Graphics::ManagedSurface *s = &_gui->_screen; + Graphics::ManagedSurface *s = &_screen; int tx = x, ty = y; if (!menu->subitems[i]->enabled) { @@ -419,8 +405,8 @@ void Menu::renderSubmenu(MenuItem *menu) { // fake it here for (int ii = 0; ii < _tempSurface.h; ii++) { const byte *src = (const byte *)_tempSurface.getBasePtr(0, ii); - byte *dst = (byte *)_gui->_screen.getBasePtr(x, y+ii); - byte pat = _gui->_patterns[kPatternCheckers2 - 1][ii % 8]; + byte *dst = (byte *)_screen.getBasePtr(x, y+ii); + byte pat = _wm->getPatterns()[kPatternCheckers2 - 1][ii % 8]; for (int j = 0; j < r->width(); j++) { if (*src != kColorGreen && (pat & (1 << (7 - (x + j) % 8)))) *dst = *src; @@ -430,20 +416,51 @@ void Menu::renderSubmenu(MenuItem *menu) { } } } else { // Delimiter - Design::drawHLine(&_gui->_screen, r->left + 1, r->right - 1, y + kMenuDropdownItemHeight / 2, 1, kColorBlack, _gui->_patterns, kPatternStripes); + bool flip = r->left & 2; + byte *ptr = (byte *)_screen.getBasePtr(r->left + 1, y + kMenuDropdownItemHeight / 2); + for (int xx = r->left + 1; xx <= r->right - 1; xx++, ptr++) { + *ptr = flip ? kColorBlack : kColorWhite; + flip = !flip; + } } y += kMenuDropdownItemHeight; } - g_system->copyRectToScreen(_gui->_screen.getBasePtr(r->left, r->top), _gui->_screen.pitch, r->left, r->top, r->width() + 3, r->height() + 3); + _contentIsDirty = true; + //g_system->copyRectToScreen(_screen.getBasePtr(r->left, r->top), _screen.pitch, r->left, r->top, r->width() + 2, r->height() + 2); +} + +bool Menu::processEvent(Common::Event &event) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + return keyEvent(event); + case Common::EVENT_LBUTTONDOWN: + return mouseClick(event.mouse.x, event.mouse.y); + case Common::EVENT_LBUTTONUP: + return mouseRelease(event.mouse.x, event.mouse.y); + case Common::EVENT_MOUSEMOVE: + return mouseMove(event.mouse.x, event.mouse.y); + default: + return false; + } +} + +bool Menu::keyEvent(Common::Event &event) { + if (event.type != Common::EVENT_KEYDOWN) + return false; + + if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) { + if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) { + return processMenuShortCut(event.kbd.flags, event.kbd.ascii); + } + } + + return false; } bool Menu::mouseClick(int x, int y) { if (_bbox.contains(x, y)) { - if (!_menuActivated) - _screenCopy.copyFrom(_gui->_screen); - for (uint i = 0; i < _items.size(); i++) if (_items[i]->bbox.contains(x, y)) { if ((uint)_activeItem == i) @@ -454,14 +471,15 @@ bool Menu::mouseClick(int x, int y) { r.right += 3; r.bottom += 3; - _gui->_screen.copyRectToSurface(_screenCopy, r.left, r.top, r); - g_system->copyRectToScreen(_gui->_screen.getBasePtr(r.left, r.top), _gui->_screen.pitch, r.left, r.top, r.width() + 1, r.height() + 1); + _wm->setFullRefresh(true); } _activeItem = i; _activeSubItem = -1; _menuActivated = true; + _contentIsDirty = true; + return true; } } else if (_menuActivated && _items[_activeItem]->subbbox.contains(x, y)) { @@ -472,11 +490,13 @@ bool Menu::mouseClick(int x, int y) { _activeSubItem = numSubItem; renderSubmenu(_items[_activeItem]); + _contentIsDirty = true; } } else if (_menuActivated && _activeItem != -1) { _activeSubItem = -1; renderSubmenu(_items[_activeItem]); + _contentIsDirty = true; } return false; @@ -495,77 +515,49 @@ bool Menu::mouseRelease(int x, int y) { _menuActivated = false; if (_activeItem != -1 && _activeSubItem != -1 && _items[_activeItem]->subitems[_activeSubItem]->enabled) - executeCommand(_items[_activeItem]->subitems[_activeSubItem]); + (*_ccallback)(_items[_activeItem]->subitems[_activeSubItem]->action, + _items[_activeItem]->subitems[_activeSubItem]->text, _cdata); _activeItem = -1; _activeSubItem = -1; + _wm->setFullRefresh(true); + return true; } return false; } -void Menu::executeCommand(MenuSubItem *subitem) { - switch(subitem->action) { - case kMenuActionAbout: - case kMenuActionNew: - case kMenuActionOpen: - case kMenuActionClose: - case kMenuActionSave: - case kMenuActionSaveAs: - case kMenuActionRevert: - case kMenuActionQuit: - - case kMenuActionUndo: - _gui->actionUndo(); - break; - case kMenuActionCut: - _gui->actionCut(); - break; - case kMenuActionCopy: - _gui->actionCopy(); - break; - case kMenuActionPaste: - _gui->actionPaste(); - break; - case kMenuActionClear: - _gui->actionClear(); - break; - - case kMenuActionCommand: - _gui->_engine->processTurn(&subitem->text, NULL); - break; - - default: - warning("Unknown action: %d", subitem->action); - - } -} - -void Menu::processMenuShortCut(byte flags, uint16 ascii) { +bool Menu::processMenuShortCut(byte flags, uint16 ascii) { ascii = tolower(ascii); if (flags & (Common::KBD_CTRL | Common::KBD_META)) { for (uint i = 0; i < _items.size(); i++) for (uint j = 0; j < _items[i]->subitems.size(); j++) if (_items[i]->subitems[j]->enabled && tolower(_items[i]->subitems[j]->shortcut) == ascii) { - executeCommand(_items[i]->subitems[j]); - break; + (*_ccallback)(_items[i]->subitems[j]->action, _items[i]->subitems[j]->text, _cdata); + return true; } } + + return false; } void Menu::enableCommand(int menunum, int action, bool state) { for (uint i = 0; i < _items[menunum]->subitems.size(); i++) if (_items[menunum]->subitems[i]->action == action) _items[menunum]->subitems[i]->enabled = state; + + _contentIsDirty = true; } void Menu::disableAllMenus() { for (uint i = 1; i < _items.size(); i++) // Leave About menu on for (uint j = 0; j < _items[i]->subitems.size(); j++) _items[i]->subitems[j]->enabled = false; + + _contentIsDirty = true; } } // End of namespace Wage diff --git a/engines/wage/menu.h b/engines/wage/macmenu.h index 916ef6d50e..e73e4c48a9 100644 --- a/engines/wage/menu.h +++ b/engines/wage/macmenu.h @@ -45,8 +45,8 @@ * */ -#ifndef WAGE_MENU_H -#define WAGE_MENU_H +#ifndef WAGE_MACMENU_H +#define WAGE_MACMENU_H namespace Wage { @@ -64,6 +64,7 @@ enum { }; enum { + kMenuHighLevel = -1, kMenuAbout = 0, kMenuFile = 1, kMenuEdit = 2, @@ -90,28 +91,42 @@ enum { kMenuActionCommand }; -class Menu { +struct MenuData { + int menunum; + const char *title; + int action; + byte shortcut; + bool enabled; +}; + +class Menu : public BaseMacWindow { public: - Menu(Gui *gui); + Menu(int id, const Common::Rect &bounds, MacWindowManager *wm); ~Menu(); - void render(); - bool mouseClick(int x, int y); - bool mouseRelease(int x, int y); - bool mouseMove(int x, int y); + void setCommandsCallback(void (*callback)(int, Common::String &, void *), void *data) { _ccallback = callback; _cdata = data; } + + void addStaticMenus(const MenuData *data); + void calcDimensions(); + + int addMenuItem(const char *name); + void addMenuSubItem(int id, const char *text, int action, int style = 0, char shortcut = 0, bool enabled = true); + void createSubMenuFromString(int id, const char *string); + void clearSubMenu(int id); + + bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false); + bool processEvent(Common::Event &event); - void regenCommandsMenu(); - void regenWeaponsMenu(); - void processMenuShortCut(byte flags, uint16 ascii); void enableCommand(int menunum, int action, bool state); void disableAllMenus(); - bool _menuActivated; + void setActive(bool active) { _menuActivated = active; } + bool hasAllFocus() { return _menuActivated; } + Common::Rect _bbox; private: - Gui *_gui; - Graphics::ManagedSurface _screenCopy; + Graphics::ManagedSurface _screen; Graphics::ManagedSurface _tempSurface; private: @@ -120,18 +135,25 @@ private: int calculateMenuWidth(MenuItem *menu); void calcMenuBounds(MenuItem *menu); void renderSubmenu(MenuItem *menu); - void createCommandsMenu(MenuItem *menu); - void createWeaponsMenu(MenuItem *menu); - void executeCommand(MenuSubItem *subitem); + + bool keyEvent(Common::Event &event); + bool mouseClick(int x, int y); + bool mouseRelease(int x, int y); + bool mouseMove(int x, int y); + + bool processMenuShortCut(byte flags, uint16 ascii); Common::Array<MenuItem *> _items; - MenuItem *_weapons; - MenuItem *_commands; const Graphics::Font *_font; + bool _menuActivated; + int _activeItem; int _activeSubItem; + + void (*_ccallback)(int action, Common::String &text, void *data); + void *_cdata; }; } // End of namespace Wage diff --git a/engines/wage/macwindow.cpp b/engines/wage/macwindow.cpp index 36b27a3e56..8903936061 100644 --- a/engines/wage/macwindow.cpp +++ b/engines/wage/macwindow.cpp @@ -45,16 +45,17 @@ * */ +#include "graphics/font.h" #include "graphics/primitives.h" #include "common/events.h" -#include "wage/wage.h" -#include "wage/gui.h" #include "wage/macwindow.h" +#include "wage/macwindowmanager.h" namespace Wage { -BaseMacWindow::BaseMacWindow(int id) : _id(id) { +BaseMacWindow::BaseMacWindow(int id, bool editable, MacWindowManager *wm) : + _id(id), _editable(editable), _wm(wm) { _callback = 0; _dataPtr = 0; @@ -63,8 +64,8 @@ BaseMacWindow::BaseMacWindow(int id) : _id(id) { _type = kWindowUnknown; } -MacWindow::MacWindow(int id, bool scrollable, bool resizable) : - BaseMacWindow(id), _scrollable(scrollable), _resizable(resizable) { +MacWindow::MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm) : + BaseMacWindow(id, editable, wm), _scrollable(scrollable), _resizable(resizable) { _active = false; _borderIsDirty = true; @@ -75,12 +76,18 @@ MacWindow::MacWindow(int id, bool scrollable, bool resizable) : _beingDragged = false; _beingResized = false; + _draggedX = _draggedY = 0; + _type = kWindowWindow; } MacWindow::~MacWindow() { } +const Graphics::Font *MacWindow::getTitleFont() { + return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); +} + void MacWindow::setActive(bool active) { if (active == _active) return; @@ -145,14 +152,6 @@ bool MacWindow::draw(Graphics::ManagedSurface *g, bool forceRedraw) { return true; } -const Graphics::Font *MacWindow::getTitleFont() { - return ((WageEngine *)g_engine)->_gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); -} - -bool MacWindow::builtInFonts() { - return ((WageEngine *)g_engine)->_gui->builtInFonts(); -} - #define ARROW_W 12 #define ARROW_H 6 const int arrowPixels[ARROW_H][ARROW_W] = { @@ -205,11 +204,11 @@ void MacWindow::drawBorder() { drawBox(g, x + width - size + 1, y + size, size - 4, height - 2 * size - 1); if (active) { - fillRect(g, x + size, y + 5, width - 2 * size - 1, 8); - fillRect(g, x + size, y + height - 13, width - 2 * size - 1, 8); - fillRect(g, x + 5, y + size, 8, height - 2 * size - 1); + fillRect(g, x + size, y + 5, width - 2 * size - 1, 8, kColorBlack); + fillRect(g, x + size, y + height - 13, width - 2 * size - 1, 8, kColorBlack); + fillRect(g, x + 5, y + size, 8, height - 2 * size - 1, kColorBlack); if (!scrollable) { - fillRect(g, x + width - 13, y + size, 8, height - 2 * size - 1); + fillRect(g, x + width - 13, y + size, 8, height - 2 * size - 1, kColorBlack); } else { int x1 = x + width - 15; int y1 = y + size + 1; @@ -219,7 +218,7 @@ void MacWindow::drawBorder() { g->hLine(x1 + xx, y1 + yy, x1 + xx, (arrowPixels[yy][xx] != 0 ? kColorBlack : kColorWhite)); } - fillRect(g, x + width - 13, y + size + ARROW_H, 8, height - 2 * size - 1 - ARROW_H * 2); + fillRect(g, x + width - 13, y + size + ARROW_H, 8, height - 2 * size - 1 - ARROW_H * 2, kColorBlack); y1 += height - 2 * size - ARROW_H - 2; for (int yy = 0; yy < ARROW_H; yy++) { @@ -239,7 +238,7 @@ void MacWindow::drawBorder() { } if (closeable) { if (_highlightedPart == kBorderCloseButton) { - fillRect(g, x + 6, y + 6, 6, 6); + fillRect(g, x + 6, y + 6, 6, 6, kColorBlack); } else { drawBox(g, x + 5, y + 5, 7, 7); } @@ -248,7 +247,7 @@ void MacWindow::drawBorder() { if (drawTitle) { const Graphics::Font *font = getTitleFont(); - int yOff = builtInFonts() ? 3 : 1; + int yOff = _wm->hasBuiltInFonts() ? 3 : 1; int w = font->getStringWidth(_title) + 10; int maxWidth = width - size * 2 - 7; @@ -329,7 +328,7 @@ bool MacWindow::processEvent(Common::Event &event) { _draggedX = event.mouse.x; _draggedY = event.mouse.y; - ((WageEngine *)g_engine)->_gui->_wm.setFullRefresh(true); + _wm->setFullRefresh(true); } if (_beingResized) { @@ -339,7 +338,7 @@ bool MacWindow::processEvent(Common::Event &event) { _draggedX = event.mouse.x; _draggedY = event.mouse.y; - ((WageEngine *)g_engine)->_gui->_wm.setFullRefresh(true); + _wm->setFullRefresh(true); (*_callback)(click, event, _dataPtr); } break; diff --git a/engines/wage/macwindow.h b/engines/wage/macwindow.h index 797e2f9c2a..4c6e9efeff 100644 --- a/engines/wage/macwindow.h +++ b/engines/wage/macwindow.h @@ -52,6 +52,8 @@ namespace Wage { +class MacWindowManager; + enum WindowType { kWindowUnknown, kWindowWindow, @@ -74,12 +76,13 @@ enum WindowClick { class BaseMacWindow { public: - BaseMacWindow(int id); + BaseMacWindow(int id, bool editable, MacWindowManager *wm); virtual ~BaseMacWindow() {} const Common::Rect &getDimensions() { return _dims; } int getId() { return _id; } WindowType getType() { return _type; } + bool isEditable() { return _editable; } Graphics::ManagedSurface *getSurface() { return &_surface; } virtual void setActive(bool active) = 0; void setDirty(bool dirty) { _contentIsDirty = dirty; } @@ -95,6 +98,8 @@ protected: int _id; WindowType _type; + bool _editable; + Graphics::ManagedSurface _surface; bool _contentIsDirty; @@ -102,11 +107,13 @@ protected: bool (*_callback)(WindowClick, Common::Event &, void *); void *_dataPtr; + + MacWindowManager *_wm; }; class MacWindow : public BaseMacWindow { public: - MacWindow(int id, bool scrollable, bool resizable); + MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm); virtual ~MacWindow(); void move(int x, int y); void resize(int w, int h); @@ -125,9 +132,8 @@ public: private: void drawBorder(); void drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h); - void fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color = kColorBlack); + void fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color); const Graphics::Font *getTitleFont(); - bool builtInFonts(); void updateInnerDims(); WindowClick isInBorder(int x, int y); diff --git a/engines/wage/macwindowmanager.cpp b/engines/wage/macwindowmanager.cpp index a86b16a8bb..5cc54d648a 100644 --- a/engines/wage/macwindowmanager.cpp +++ b/engines/wage/macwindowmanager.cpp @@ -48,35 +48,96 @@ #include "common/array.h" #include "common/events.h" #include "common/list.h" +#include "common/unzip.h" #include "common/system.h" +#include "common/stream.h" +#include "graphics/cursorman.h" +#include "graphics/fonts/bdf.h" #include "graphics/managed_surface.h" +#include "graphics/palette.h" +#include "graphics/primitives.h" -#include "wage/wage.h" -#include "wage/design.h" -#include "wage/gui.h" -#include "wage/macwindow.h" #include "wage/macwindowmanager.h" +#include "wage/macwindow.h" +#include "wage/macmenu.h" namespace Wage { -enum { - kPatternCheckers = 1 +static const byte palette[] = { + 0, 0, 0, // Black + 0x80, 0x80, 0x80, // Gray + 0xff, 0xff, 0xff, // White + 0x00, 0xff, 0x00, // Green + 0x00, 0xcf, 0x00 // Green2 +}; + +static byte fillPatterns[][8] = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, // kPatternSolid + { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, // kPatternStripes + { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }, // kPatternCheckers + { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa } // kPatternCheckers2 }; -static byte fillPatterns[][8] = { { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 } // kPatternCheckers +static const byte macCursorArrow[] = { + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, + 2, 0, 0, 0, 2, 3, 3, 3, 3, 3, 3, + 2, 0, 0, 0, 0, 2, 3, 3, 3, 3, 3, + 2, 0, 0, 0, 0, 0, 2, 3, 3, 3, 3, + 2, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, + 2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, + 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, + 2, 0, 0, 2, 0, 0, 2, 3, 3, 3, 3, + 2, 0, 2, 3, 2, 0, 0, 2, 3, 3, 3, + 2, 2, 3, 3, 2, 0, 0, 2, 3, 3, 3, + 2, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, + 3, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3 }; +static const byte macCursorBeam[] = { + 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, + 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, + 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, +}; MacWindowManager::MacWindowManager() { _screen = 0; _lastId = 0; _activeWindow = -1; + _menu = 0; + _fullRefresh = true; + _builtInFonts = true; + for (int i = 0; i < ARRAYSIZE(fillPatterns); i++) _patterns.push_back(fillPatterns[i]); + + loadFonts(); + + g_system->getPaletteManager()->setPalette(palette, 0, ARRAYSIZE(palette) / 3); + + CursorMan.replaceCursorPalette(palette, 0, ARRAYSIZE(palette) / 3); + CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); + _cursorIsArrow = true; + CursorMan.showMouse(true); } MacWindowManager::~MacWindowManager() { @@ -84,8 +145,8 @@ MacWindowManager::~MacWindowManager() { delete _windows[i]; } -MacWindow *MacWindowManager::addWindow(bool scrollable, bool resizable) { - MacWindow *w = new MacWindow(_lastId, scrollable, resizable); +MacWindow *MacWindowManager::addWindow(bool scrollable, bool resizable, bool editable) { + MacWindow *w = new MacWindow(_lastId, scrollable, resizable, editable, this); _windows.push_back(w); _windowStack.push_back(w); @@ -97,6 +158,16 @@ MacWindow *MacWindowManager::addWindow(bool scrollable, bool resizable) { return w; } +Menu *MacWindowManager::addMenu() { + _menu = new Menu(_lastId, _screen->getBounds(), this); + + _windows.push_back(_menu); + + _lastId++; + + return _menu; +} + void MacWindowManager::setActive(int id) { if (_activeWindow == id) return; @@ -114,6 +185,61 @@ void MacWindowManager::setActive(int id) { _fullRefresh = true; } +struct PlotData { + Graphics::ManagedSurface *surface; + Patterns *patterns; + uint fillType; + int thickness; + + PlotData(Graphics::ManagedSurface *s, Patterns *p, int f, int t) : + surface(s), patterns(p), fillType(f), thickness(t) {} +}; + +static void drawPixel(int x, int y, int color, void *data) { + PlotData *p = (PlotData *)data; + + if (p->fillType > p->patterns->size()) + return; + + byte *pat = p->patterns->operator[](p->fillType - 1); + + if (p->thickness == 1) { + if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) { + uint xu = (uint)x; // for letting compiler optimize it + uint yu = (uint)y; + + *((byte *)p->surface->getBasePtr(xu, yu)) = + (pat[yu % 8] & (1 << (7 - xu % 8))) ? + color : kColorWhite; + } + } else { + int x1 = x; + int x2 = x1 + p->thickness; + int y1 = y; + int y2 = y1 + p->thickness; + + for (y = y1; y < y2; y++) + for (x = x1; x < x2; x++) + if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) { + uint xu = (uint)x; // for letting compiler optimize it + uint yu = (uint)y; + *((byte *)p->surface->getBasePtr(xu, yu)) = + (pat[yu % 8] & (1 << (7 - xu % 8))) ? + color : kColorWhite; + } + } +} + +void MacWindowManager::drawDesktop() { + Common::Rect r(_screen->getBounds()); + + PlotData pd(_screen, &_patterns, kPatternCheckers, 1); + + Graphics::drawRoundRect(r, kDesktopArc, kColorBlack, true, drawPixel, &pd); + + g_system->copyRectToScreen(_screen->getPixels(), _screen->pitch, 0, 0, _screen->w, _screen->h); +} + void MacWindowManager::draw() { assert(_screen); @@ -132,21 +258,35 @@ void MacWindowManager::draw() { } } - _fullRefresh = false; -} + // Menu is drawn on top of everything and always + if (_menu) + _menu->draw(_screen, _fullRefresh); -void MacWindowManager::drawDesktop() { - Common::Rect r(_screen->getBounds()); - - Design::drawFilledRoundRect(_screen, r, kDesktopArc, kColorBlack, _patterns, kPatternCheckers); - g_system->copyRectToScreen(_screen->getPixels(), _screen->pitch, 0, 0, _screen->w, _screen->h); + _fullRefresh = false; } bool MacWindowManager::processEvent(Common::Event &event) { + // Menu gets events first fir shortcuts and menu bar + if (_menu && _menu->processEvent(event)) + return true; + if (event.type != Common::EVENT_MOUSEMOVE && event.type != Common::EVENT_LBUTTONDOWN && event.type != Common::EVENT_LBUTTONUP) return false; + if (_windows[_activeWindow]->isEditable() && _windows[_activeWindow]->getType() == kWindowWindow && + ((MacWindow *)_windows[_activeWindow])->getInnerDimensions().contains(event.mouse.x, event.mouse.y)) { + if (_cursorIsArrow) { + CursorMan.replaceCursor(macCursorBeam, 11, 16, 3, 8, 3); + _cursorIsArrow = false; + } + } else { + if (_cursorIsArrow == false) { + CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); + _cursorIsArrow = true; + } + } + for (Common::List<BaseMacWindow *>::const_iterator it = _windowStack.end(); it != _windowStack.begin();) { it--; BaseMacWindow *w = *it; @@ -162,4 +302,79 @@ bool MacWindowManager::processEvent(Common::Event &event) { return false; } +////////////////////// +// Font stuff +////////////////////// +void MacWindowManager::loadFonts() { + Common::Archive *dat; + + dat = Common::makeZipArchive("classicmacfonts.dat"); + + if (!dat) { + warning("Could not find classicmacfonts.dat. Falling back to built-in fonts"); + _builtInFonts = true; + + return; + } + + Common::ArchiveMemberList list; + dat->listMembers(list); + + for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { + Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName()); + + Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream); + + delete stream; + + Common::String fontName = (*it)->getName(); + + // Trim the .bdf extension + for (int i = fontName.size() - 1; i >= 0; --i) { + if (fontName[i] == '.') { + while ((uint)i < fontName.size()) { + fontName.deleteLastChar(); + } + break; + } + } + + FontMan.assignFontToName(fontName, font); + + debug(2, " %s", fontName.c_str()); + } + + _builtInFonts = false; + + delete dat; +} + +const Graphics::Font *MacWindowManager::getFont(const char *name, Graphics::FontManager::FontUsage fallback) { + const Graphics::Font *font = 0; + + if (!_builtInFonts) { + font = FontMan.getFontByName(name); + + if (!font) + warning("Cannot load font %s", name); + } + + if (_builtInFonts || !font) + font = FontMan.getFontByUsage(fallback); + + return font; +} + +///////////////// +// Cursor stuff +///////////////// +void MacWindowManager::pushArrowCursor() { + CursorMan.pushCursor(macCursorArrow, 11, 16, 1, 1, 3); +} + +void MacWindowManager::popCursor() { + CursorMan.popCursor(); +} + + } // End of namespace Wage diff --git a/engines/wage/macwindowmanager.h b/engines/wage/macwindowmanager.h index 06b7689706..13f85cddd4 100644 --- a/engines/wage/macwindowmanager.h +++ b/engines/wage/macwindowmanager.h @@ -48,9 +48,43 @@ #ifndef WAGE_MACWINDOWMANAGER_H #define WAGE_MACWINDOWMANAGER_H +#include "common/array.h" +#include "common/list.h" +#include "common/events.h" +#include "common/archive.h" + +#include "graphics/fontman.h" + +namespace Graphics { +class ManagedSurface; +} + namespace Wage { +enum { + kDesktopArc = 7 +}; + +enum { + kColorBlack = 0, + kColorGray = 1, + kColorWhite = 2, + kColorGreen = 3, + kColorGreen2 = 4 +}; + +enum { + kPatternSolid = 1, + kPatternStripes = 2, + kPatternCheckers = 3, + kPatternCheckers2 = 4 +}; + +class BaseMacWindow; class MacWindow; +class Menu; + +typedef Common::Array<byte *> Patterns; class MacWindowManager { public: @@ -58,8 +92,11 @@ public: ~MacWindowManager(); void setScreen(Graphics::ManagedSurface *screen) { _screen = screen; } + bool hasBuiltInFonts() { return _builtInFonts; } + const Graphics::Font *getFont(const char *name, Graphics::FontManager::FontUsage fallback); - MacWindow *addWindow(bool scrollable, bool resizable); + MacWindow *addWindow(bool scrollable, bool resizable, bool editable); + Menu *addMenu(); void setActive(int id); void setFullRefresh(bool redraw) { _fullRefresh = true; } @@ -70,8 +107,15 @@ public: BaseMacWindow *getWindow(int id) { return _windows[id]; } + Patterns &getPatterns() { return _patterns; } + void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color); + + void pushArrowCursor(); + void popCursor(); + private: void drawDesktop(); + void loadFonts(); private: Graphics::ManagedSurface *_screen; @@ -85,6 +129,11 @@ private: bool _fullRefresh; Patterns _patterns; + + Menu *_menu; + + bool _builtInFonts; + bool _cursorIsArrow; }; } // End of namespace Wage diff --git a/engines/wage/module.mk b/engines/wage/module.mk index d65934fc2b..e150d5f27e 100644 --- a/engines/wage/module.mk +++ b/engines/wage/module.mk @@ -9,9 +9,9 @@ MODULE_OBJS := \ entities.o \ gui.o \ gui-console.o \ + macmenu.o \ macwindow.o \ macwindowmanager.o \ - menu.o \ randomhat.o \ script.o \ sound.o \ diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp index 278badd616..567e2768d8 100644 --- a/engines/wage/wage.cpp +++ b/engines/wage/wage.cpp @@ -180,13 +180,6 @@ void WageEngine::processEvents() { break; } - if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) { - if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) { - _gui->processMenuShortCut(event.kbd.flags, event.kbd.ascii); - } - break; - } - if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) { _inputText += (char)event.kbd.ascii; _gui->drawInput(); @@ -227,7 +220,6 @@ void WageEngine::gameOver() { _gui->disableAllMenus(); _gui->enableNewGameMenus(); - _gui->_menuDirty = true; } bool WageEngine::saveDialog() { diff --git a/engines/wage/wage.h b/engines/wage/wage.h index 87009c2350..eb50a2e3dd 100644 --- a/engines/wage/wage.h +++ b/engines/wage/wage.h @@ -103,14 +103,6 @@ enum { // the current limitation is 32 debug levels (1 << 31 is the last one) }; -enum { - kColorBlack = 0, - kColorGray = 1, - kColorWhite = 2, - kColorGreen = 3, - kColorGreen2 = 4 -}; - Common::String readPascalString(Common::SeekableReadStream *in); Common::Rect *readRect(Common::SeekableReadStream *in); const char *getIndefiniteArticle(const Common::String &word); @@ -118,8 +110,6 @@ const char *prependGenderSpecificPronoun(int gender); const char *getGenderSpecificPronoun(int gender, bool capitalize); bool isStorageScene(const Common::String &name); -typedef Common::Array<byte *> Patterns; - class WageEngine : public Engine { friend class Dialog; public: diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp index 954a425b7b..53fc1b4742 100644 --- a/engines/wage/world.cpp +++ b/engines/wage/world.cpp @@ -73,6 +73,8 @@ World::World(WageEngine *engine) { _weaponMenuDisabled = true; _engine = engine; + + _patterns = new Patterns; } World::~World() { @@ -88,8 +90,10 @@ World::~World() { for (uint i = 0; i < _orderedScenes.size(); i++) delete _orderedScenes[i]; - for (uint i = 0; i < _patterns.size(); i++) - free(_patterns[i]); + for (uint i = 0; i < _patterns->size(); i++) + free(_patterns->operator[](i)); + + delete _patterns; delete _globalScript; @@ -261,7 +265,7 @@ bool World::loadWorld(Common::MacResManager *resMan) { byte *pattern = (byte *)malloc(8); res->read(pattern, 8); - _patterns.push_back(pattern); + _patterns->push_back(pattern); } delete res; @@ -274,7 +278,7 @@ bool World::loadWorld(Common::MacResManager *resMan) { byte *pattern = (byte *)malloc(8); res->read(pattern, 8); - _patterns.push_back(pattern); + _patterns->push_back(pattern); } } delete res; diff --git a/engines/wage/world.h b/engines/wage/world.h index 355d660c8d..468bedbc59 100644 --- a/engines/wage/world.h +++ b/engines/wage/world.h @@ -48,6 +48,8 @@ #ifndef WAGE_WORLD_H #define WAGE_WORLD_H +#include "wage/macwindowmanager.h" + namespace Wage { class Sound; @@ -85,7 +87,7 @@ public: ObjArray _orderedObjs; ChrArray _orderedChrs; Common::Array<Sound *> _orderedSounds; - Patterns _patterns; + Patterns *_patterns; Scene *_storageScene; Chr *_player; //List<MoveListener> moveListeners; 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:" |