diff options
| author | David Corrales | 2007-06-23 18:51:33 +0000 |
|---|---|---|
| committer | David Corrales | 2007-06-23 18:51:33 +0000 |
| commit | cacd7a28fd51d960947de88abbf30c487e66529d (patch) | |
| tree | f3baa59853bfb307e452b86b9d93c4737b1fa6ab /engines/agos | |
| parent | 0ac96302fe9c04df79cb01a77d19535b45fe2db0 (diff) | |
| parent | 90c2210dae8c91fa8babc6b05564e15c9d445d18 (diff) | |
| download | scummvm-rg350-cacd7a28fd51d960947de88abbf30c487e66529d.tar.gz scummvm-rg350-cacd7a28fd51d960947de88abbf30c487e66529d.tar.bz2 scummvm-rg350-cacd7a28fd51d960947de88abbf30c487e66529d.zip | |
Merged the FSNode branch with trunk r27031:27680
svn-id: r27681
Diffstat (limited to 'engines/agos')
41 files changed, 2269 insertions, 1126 deletions
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 33737057f8..c98257f028 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -124,6 +124,10 @@ AGOSEngine::AGOSEngine(OSystem *syst) _tableIndexBase = 0; _textIndexBase = 0; + _numMusic = 0; + _numSFX = 0; + _numSpeech = 0; + _numBitArray1 = 0; _numBitArray2 = 0; _numBitArray3 = 0; @@ -132,6 +136,7 @@ AGOSEngine::AGOSEngine(OSystem *syst) _numVars = 0; _numVideoOpcodes = 0; _vgaBaseDelay = 0; + _vgaPeriod = 0; _strippedTxtMem = 0; _textMem = 0; @@ -197,13 +202,10 @@ AGOSEngine::AGOSEngine(OSystem *syst) _litBoxFlag = 0; _mortalFlag = 0; _displayScreen = false; - _updateScreen = false; _syncFlag2 = 0; _inCallBack = 0; _cepeFlag = 0; - _copyPartialMode = 0; _fastMode = 0; - _useBackGround = 0; _backFlag = 0; @@ -298,6 +300,8 @@ AGOSEngine::AGOSEngine(OSystem *syst) _leftButtonDown = 0; _rightButtonDown = 0; _clickOnly = 0; + _leftClick = 0; + _oneClick = 0; _noRightClick = false; _leftButton = 0; @@ -312,7 +316,6 @@ AGOSEngine::AGOSEngine(OSystem *syst) _scrollUpHitArea = 0; _scrollDownHitArea = 0; - _noOverWrite = 0; _rejectBlock = false; @@ -331,6 +334,7 @@ AGOSEngine::AGOSEngine(OSystem *syst) _showPreposition = 0; _showMessageFlag = 0; + _newDirtyClip = false; _copyScnFlag = 0; _vgaSpriteChanged = 0; @@ -348,8 +352,6 @@ AGOSEngine::AGOSEngine(OSystem *syst) _curSfxFile = 0; _syncCount = 0; - _timer5 = 0; - _timer4 = 0; _iconToggleCount = 0; _voiceCount = 0; @@ -466,6 +468,9 @@ AGOSEngine::AGOSEngine(OSystem *syst) _planarBuf = 0; + _midiEnabled = false; + _nativeMT32 = false; + _vgaTickCounter = 0; _moviePlay = 0; @@ -494,7 +499,6 @@ AGOSEngine::AGOSEngine(OSystem *syst) _noOracleScroll = 0; _backGroundBuf = 0; - _frontBuf = 0; _backBuf = 0; _scaleBuf = 0; @@ -566,34 +570,34 @@ int AGOSEngine::init() { _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - // Setup midi driver - MidiDriver *driver = 0; - if (getGameType() == GType_FF || getGameType() == GType_PP || getGameId() == GID_SIMON1CD32) { - driver = MidiDriver::createMidi(MD_NULL); - _native_mt32 = false; - } else { + if ((getGameType() == GType_SIMON2 && getPlatform() == Common::kPlatformWindows) || + (getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformWindows) || + ((getFeatures() & GF_TALKIE) && getPlatform() == Common::kPlatformAcorn) || + (getPlatform() == Common::kPlatformPC)) { + + // Setup midi driver int midiDriver = MidiDriver::detectMusicDriver(MDT_ADLIB | MDT_MIDI); - _native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - driver = MidiDriver::createMidi(midiDriver); - if (_native_mt32) { + _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver *driver = MidiDriver::createMidi(midiDriver); + if (_nativeMT32) { driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); } - } - _midi.mapMT32toGM (getGameType() != GType_SIMON2 && !_native_mt32); + _midi.mapMT32toGM (getGameType() != GType_SIMON2 && !_nativeMT32); + + _midi.setDriver(driver); + int ret = _midi.open(); + if (ret) + warning("MIDI Player init failed: \"%s\"", _midi.getErrorName (ret)); - _midi.setDriver(driver); - int ret = _midi.open(); - if (ret) - warning("MIDI Player init failed: \"%s\"", _midi.getErrorName (ret)); - _midi.setVolume(ConfMan.getInt("music_volume")); + _midi.setVolume(ConfMan.getInt("music_volume")); - if (ConfMan.hasKey("music_mute") && ConfMan.getBool("music_mute") == 1) - _midi.pause(_musicPaused ^= 1); + + _midiEnabled = true; + } // allocate buffers _backGroundBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); - _frontBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); if (getGameType() == GType_FF || getGameType() == GType_PP) { _backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); @@ -607,7 +611,11 @@ int AGOSEngine::init() { } else if (getGameType() == GType_WW || getGameType() == GType_ELVIRA2) { _window4BackScn = (byte *)calloc(224 * 127, 1); } else if (getGameType() == GType_ELVIRA1) { - _window4BackScn = (byte *)calloc(224 * 127, 1); + if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_DEMO)) { + _window4BackScn = (byte *)calloc(224 * 196, 1); + } else { + _window4BackScn = (byte *)calloc(224 * 144, 1); + } _window6BackScn = (byte *)calloc(48 * 80, 1); } @@ -618,6 +626,14 @@ int AGOSEngine::init() { _moviePlay = new MoviePlayer(this, _mixer); + if (ConfMan.hasKey("music_mute") && ConfMan.getBool("music_mute") == 1) { + _musicPaused = true; + if (_midiEnabled) { + _midi.pause(_musicPaused); + } + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, 0); + } + if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) { if (getGameId() == GID_SIMON1DOS) _midi._enable_sfx ^= 1; @@ -693,6 +709,7 @@ void AGOSEngine_PuzzlePack::setupGame() { _tableMemSize = 200000; _frameCount = 1; _vgaBaseDelay = 5; + _vgaPeriod = (getGameId() == GID_DIMP) ? 35 : 30; _numBitArray1 = 128; _numItemStore = 10; _numTextBoxes = 40; @@ -713,6 +730,7 @@ void AGOSEngine_Feeble::setupGame() { _tableMemSize = 200000; _frameCount = 1; _vgaBaseDelay = 5; + _vgaPeriod = 50; _numBitArray1 = 16; _numBitArray2 = 16; _numBitArray3 = 16; @@ -736,19 +754,24 @@ void AGOSEngine_Simon2::setupGame() { _itemMemSize = 20000; _tableMemSize = 100000; // Check whether to use MT-32 MIDI tracks in Simon the Sorcerer 2 - if ((getGameType() == GType_SIMON2) && _native_mt32) + if (getGameType() == GType_SIMON2 && _nativeMT32) _musicIndexBase = (1128 + 612) / 4; else _musicIndexBase = 1128 / 4; _soundIndexBase = 1660 / 4; _frameCount = 1; _vgaBaseDelay = 1; + _vgaPeriod = 45; _numBitArray1 = 16; _numBitArray2 = 16; _numItemStore = 10; _numTextBoxes = 20; _numVars = 255; + _numMusic = 93; + _numSFX = 222; + _numSpeech = 3632; + AGOSEngine::setupGame(); } @@ -768,12 +791,17 @@ void AGOSEngine_Simon1::setupGame() { _soundIndexBase = 0; _frameCount = 1; _vgaBaseDelay = 1; + _vgaPeriod = 50; _numBitArray1 = 16; _numBitArray2 = 16; _numItemStore = 10; _numTextBoxes = 20; _numVars = 255; + _numMusic = 34; + _numSFX = 127; + _numSpeech = 1996; + AGOSEngine::setupGame(); } @@ -789,12 +817,15 @@ void AGOSEngine_Waxworks::setupGame() { _tableMemSize = 50000; _frameCount = 4; _vgaBaseDelay = 1; + _vgaPeriod = 50; _numBitArray1 = 16; _numBitArray2 = 15; _numItemStore = 50; _numTextBoxes = 10; _numVars = 255; + _numMusic = 9; + AGOSEngine::setupGame(); } @@ -810,11 +841,14 @@ void AGOSEngine_Elvira2::setupGame() { _tableMemSize = 100000; _frameCount = 4; _vgaBaseDelay = 1; + _vgaPeriod = 50; _numBitArray1 = 16; _numBitArray2 = 15; _numItemStore = 50; _numVars = 255; + _numMusic = 9; + AGOSEngine::setupGame(); } @@ -830,8 +864,11 @@ void AGOSEngine_Elvira1::setupGame() { _tableMemSize = 256000; _frameCount = 4; _vgaBaseDelay = 1; + _vgaPeriod = 50; _numVars = 512; + _numMusic = 14; + AGOSEngine::setupGame(); } @@ -876,7 +913,10 @@ void AGOSEngine::setupGame() { } AGOSEngine::~AGOSEngine() { - delete _gameFile; + // Sync with AGOSEngine::shutdown() + // In Simon 2, this gets deleted along with _sound further down + if (getGameType() != GType_SIMON2) + delete _gameFile; _midi.close(); @@ -892,7 +932,6 @@ AGOSEngine::~AGOSEngine() { free(_textMem); free(_backGroundBuf); - free(_frontBuf); free(_backBuf); free(_scaleBuf); @@ -906,7 +945,7 @@ AGOSEngine::~AGOSEngine() { delete _dummyItem2; delete _dummyItem3; - delete [] _dummyWindow; + delete _dummyWindow; delete [] _windowList; delete _debugger; @@ -925,13 +964,17 @@ void AGOSEngine::pause() { bool music_status = _musicPaused; _midi.pause(true); + _mixer->pauseAll(true); _sound->ambientPause(true); + while (_pause) { delay(1); if (_keyPressed == 'p') _pause = 0; } + _midi.pause(music_status); + _mixer->pauseAll(false); _sound->ambientPause(ambient_status); } @@ -982,7 +1025,7 @@ int AGOSEngine::go() { } if (getGameType() == GType_ELVIRA1 && getFeatures() & GF_DEMO) { - loadMusic(0); + playMusic(0, 0); } if ((getPlatform() == Common::kPlatformAmiga || getPlatform() == Common::kPlatformMacintosh) && @@ -1004,18 +1047,44 @@ int AGOSEngine::go() { } void AGOSEngine::shutdown() { - delete _gameFile; + // Sync with AGOSEngine::~AGOSEngine() + // In Simon 2, this gets deleted along with _sound further down + if (getGameType() != GType_SIMON2) + delete _gameFile; _midi.close(); - free(_stringTabPtr); - free(_itemArrayPtr); free(_itemHeapPtr - _itemHeapCurPos); free(_tablesHeapPtr - _tablesHeapCurPos); - free(_tblList); - free(_zoneBuffers); - free(_iconFilePtr); + free(_gameOffsetsPtr); + free(_iconFilePtr); + free(_itemArrayPtr); + free(_stringTabPtr); + free(_strippedTxtMem); + free(_tblList); + free(_textMem); + + free(_backGroundBuf); + free(_backBuf); + free(_scaleBuf); + + free(_window4BackScn); + free(_window6BackScn); + + free(_variableArray); + free(_variableArray2); + + delete _dummyItem1; + delete _dummyItem2; + delete _dummyItem3; + + delete _dummyWindow; + delete [] _windowList; + + delete _debugger; + delete _moviePlay; + delete _sound; _system->quit(); } diff --git a/engines/agos/agos.h b/engines/agos/agos.h index d51c1169cf..e487c38cc7 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -90,7 +90,8 @@ struct VgaSprite { int16 x, y; uint16 flags; uint16 priority; - uint16 windowNum, zoneNum; + uint16 windowNum; + uint16 zoneNum; VgaSprite() { memset(this, 0, sizeof(*this)); } }; @@ -117,8 +118,9 @@ struct AnimTable { int16 y; uint16 width; uint16 height; - uint16 window; + uint16 windowNum; uint16 id; + uint16 zoneNum; AnimTable() { memset(this, 0, sizeof(*this)); } }; @@ -169,7 +171,7 @@ public: void setupVgaOpcodes(); VgaOpcodeProc _vga_opcode_table[100]; - uint _numVideoOpcodes; + uint8 _numVideoOpcodes; virtual void setupVideoOpcodes(VgaOpcodeProc *op); @@ -187,7 +189,7 @@ public: const char *getFileName(int type) const; protected: - void playSting(uint a); + void playSting(uint16 a); const byte *_vcPtr; /* video code ptr */ uint16 _vc_get_out_of_code; @@ -195,18 +197,22 @@ protected: uint32 *_gameOffsetsPtr; - uint _numBitArray1, _numBitArray2, _numBitArray3; - uint _numItemStore, _numVars; - uint _vgaBaseDelay; + uint8 _numMusic, _numSFX; + uint16 _numSpeech; - uint _musicIndexBase; - uint _soundIndexBase; - uint _tableIndexBase; - uint _textIndexBase; + uint8 _numBitArray1, _numBitArray2, _numBitArray3, _numItemStore; + uint16 _numVars; - uint _itemMemSize; - uint _tableMemSize; - uint _vgaMemSize; + uint8 _vgaBaseDelay, _vgaPeriod; + + uint16 _musicIndexBase; + uint16 _soundIndexBase; + uint16 _tableIndexBase; + uint16 _textIndexBase; + + uint32 _itemMemSize; + uint32 _tableMemSize; + uint32 _vgaMemSize; const GameSpecificSettings *gss; @@ -255,9 +261,9 @@ protected: Subroutine *_subroutineList; uint _subroutine; - uint _dxSurfacePitch; + uint16 _dxSurfacePitch; - uint _recursionDepth; + uint8 _recursionDepth; uint32 _lastVgaTick; @@ -273,14 +279,10 @@ protected: bool _litBoxFlag; bool _mortalFlag; bool _displayScreen; - bool _updateScreen; bool _syncFlag2; bool _inCallBack; bool _cepeFlag; - byte _copyPartialMode; bool _fastMode; - bool _useBackGround; - bool _backFlag; uint16 _debugMode; @@ -297,9 +299,10 @@ protected: bool _vgaVar9; int16 _chanceModifier; bool _restoreWindow6; - int _scrollX, _scrollXMax, _scrollWidth; - int _scrollY, _scrollYMax, _scrollHeight; - int _scrollCount, _scrollFlag; + int16 _scrollX, _scrollXMax; + int16 _scrollY, _scrollYMax; + int16 _scrollCount, _scrollFlag; + uint16 _scrollWidth, _scrollHeight; const byte *_scrollImage; byte _boxStarHeight; @@ -318,8 +321,8 @@ protected: int _agosMenu; byte _textMenu[10]; - uint _currentRoom, _superRoomNumber; - uint _wallOn; + uint16 _currentRoom, _superRoomNumber; + uint8 _wallOn; uint16 _hyperLink, _newLines; uint16 _oracleMaxScrollY, _noOracleScroll; @@ -355,8 +358,8 @@ protected: uint16 _windowNum; - uint _printCharCurPos, _printCharMaxPos, _printCharPixelCount; - uint _numLettersToPrint; + int16 _printCharCurPos, _printCharMaxPos, _printCharPixelCount; + uint16 _numLettersToPrint; uint _numTextBoxes; @@ -381,7 +384,7 @@ protected: byte _leftButtonDown; byte _leftButton, _leftButtonCount, _leftButtonOld; byte _rightButtonDown; - bool _clickOnly; + bool _clickOnly, _leftClick, _oneClick; bool _noRightClick; Item *_dummyItem1; @@ -412,6 +415,7 @@ protected: bool _showPreposition; bool _showMessageFlag; + bool _newDirtyClip; uint _copyScnFlag, _vgaSpriteChanged; byte *_block, *_blockEnd; @@ -423,7 +427,7 @@ protected: byte *_curVgaFile2; byte *_curSfxFile; - uint16 _syncCount, _timer5, _timer4; + uint16 _syncCount; int16 _iconToggleCount, _voiceCount; uint32 _lastTickCount, _thisTickCount; @@ -439,7 +443,7 @@ protected: int16 _baseY; float _scale; Common::Rect _feebleRect; - int _scaleX, _scaleY, _scaleWidth, _scaleHeight; + int16 _scaleX, _scaleY, _scaleWidth, _scaleHeight; VgaTimerEntry *_nextVgaTimerToProcess; @@ -476,7 +480,7 @@ protected: HitArea _hitAreas[250]; - AnimTable _screenAnim1[60]; + AnimTable _screenAnim1[90]; VgaPointersEntry _vgaBufferPointers[450]; VgaSprite _vgaSprites[200]; VgaSleepStruct _waitEndTable[60]; @@ -499,9 +503,9 @@ protected: byte _videoBuf1[32000]; uint16 _videoWindows[128]; - uint16 _window3Flag; - uint16 _window4Flag; - uint16 _window6Flag; + uint8 _window3Flag; + uint8 _window4Flag; + uint8 _window6Flag; byte *_window4BackScn; byte *_window6BackScn; @@ -515,7 +519,8 @@ protected: byte _lettersToPrintBuf[80]; MidiPlayer _midi; - bool _native_mt32; + bool _midiEnabled; + bool _nativeMT32; int _vgaTickCounter; @@ -543,7 +548,6 @@ protected: bool _oopsValid; byte *_backGroundBuf; - byte *_frontBuf; byte *_backBuf; byte *_scaleBuf; @@ -567,7 +571,7 @@ protected: void setupStringTable(byte *mem, int num); void setupLocalStringTable(byte *mem, int num); void readGamePcText(Common::SeekableReadStream *in); - void readItemChildren(Common::SeekableReadStream *in, Item *item, uint tmp); + virtual void readItemChildren(Common::SeekableReadStream *in, Item *item, uint tmp); void readItemFromGamePc(Common::SeekableReadStream *in, Item *item); void loadGamePcFile(); void readGamePcFile(Common::SeekableReadStream *in); @@ -597,7 +601,7 @@ protected: void allocItemHeap(); void allocTablesHeap(); - Subroutine *createSubroutine(uint a); + Subroutine *createSubroutine(uint16 a); void readSubroutine(Common::SeekableReadStream *in, Subroutine *sub); SubroutineLine *createSubroutineLine(Subroutine *sub, int a); void readSubroutineLine(Common::SeekableReadStream *in, SubroutineLine *new_table, Subroutine *sub); @@ -628,9 +632,9 @@ protected: uint getVarWrapper(); uint getVarOrWord(); uint getVarOrByte(); - uint readVariable(uint variable); + uint readVariable(uint16 variable); void writeNextVarContents(uint16 contents); - void writeVariable(uint variable, uint16 contents); + void writeVariable(uint16 variable, uint16 contents); Item *derefItem(uint item); Item *getNextItemPtr(); @@ -641,11 +645,11 @@ protected: Item *actor(); void showMessageFormat(const char *s, ...); - const byte *getStringPtrByID(uint stringId); - const byte *getLocalStringByID(uint stringId); + const byte *getStringPtrByID(uint16 stringId); + const byte *getLocalStringByID(uint16 stringId); uint getNextStringID(); - void addTimeEvent(uint timeout, uint subroutine_id); + void addTimeEvent(uint16 timeout, uint16 subroutine_id); void delTimeEvent(TimeEvent *te); Item *findInByClass(Item *i, int16 m); @@ -665,8 +669,8 @@ protected: void setItemParent(Item *item, Item *parent); void setItemState(Item *item, int value); - void stopAnimate(uint a); - void stopAnimateSimon2(uint a, uint b); + void stopAnimate(uint16 a); + void stopAnimateSimon2(uint16 a, uint16 b); void enableBox(uint hitarea); void disableBox(uint hitarea); @@ -729,11 +733,11 @@ protected: void mouseOff(); void mouseOn(); - bool loadRoomItems(uint item); + bool loadRoomItems(uint16 item); - virtual bool loadTablesIntoMem(uint subr_id); - bool loadXTablesIntoMem(uint subr_id); - void loadTextIntoMem(uint stringId); + virtual bool loadTablesIntoMem(uint16 subr_id); + bool loadXTablesIntoMem(uint16 subr_id); + void loadTextIntoMem(uint16 stringId); uint loadTextFile(const char *filename, byte *dst); Common::File *openTablesFile(const char *filename); @@ -777,7 +781,8 @@ protected: virtual void handleMouseMoved(); virtual void drawMousePointer(); - virtual void addArrows(WindowBlock *window); + void drawArrow(uint16 x, uint16 y, int8 dir); + virtual void addArrows(WindowBlock *window, uint8 num); void removeArrows(WindowBlock *window, uint num); virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y); @@ -801,14 +806,13 @@ protected: void justifyStart(); void justifyOutPut(byte chr); - void loadZone(uint zoneNum); + void loadZone(uint16 zoneNum); void animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, int16 x, int16 y, uint16 palette, bool vgaScript = false); void setImage(uint16 vga_res_id, bool vgaScript = false); void setWindowImage(uint16 mode, uint16 vga_res_id); void setWindowImageEx(uint16 mode, uint16 vga_res); - void playSpeech(uint speech_id, uint vga_sprite_id); void skipSpeech(); bool printNameOf(Item *item, uint x, uint y); @@ -1051,9 +1055,10 @@ public: int16 levelOf(Item *item); int16 moreText(Item *i); void lobjFunc(Item *i, const char *f); - uint confirmQuit(); + uint confirmYesOrNo(uint16 x, uint16 y); uint continueOrQuit(); void printScroll(); + virtual void printStats(); void synchChain(Item *i); protected: @@ -1082,10 +1087,10 @@ protected: void checkScrollY(int16 y, int16 ypos); void centreScroll(); - void clearVideoWindow(uint windowNum, uint color); - void clearVideoBackGround(uint windowNum, uint color); + void clearVideoWindow(uint16 windowNum, uint16 color); + void clearVideoBackGround(uint16 windowNum, uint16 color); - void setPaletteSlot(uint srcOffs, uint dstOffs); + void setPaletteSlot(uint16 srcOffs, uint8 dstOffs); void checkWaitEndTable(); void startOverlayAnims(); @@ -1116,12 +1121,12 @@ protected: void sendWindow(uint a); - void restoreWindow(WindowBlock *window); - void colorWindow(WindowBlock *window); + virtual void colorWindow(WindowBlock *window); + void colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, uint16 h); - void restoreBlock(uint h, uint w, uint y, uint x); + void restoreWindow(WindowBlock *window); + void restoreBlock(uint16 h, uint16 w, uint16 y, uint16 x); - byte *getFrontBuf(); byte *getBackBuf(); byte *getBackGround(); byte *getScaleBuf(); @@ -1129,9 +1134,9 @@ protected: byte *convertImage(VC10_state *state, bool compressed); bool decrunchFile(byte *src, byte *dst, uint32 size); - void loadVGABeardFile(uint id); - void loadVGAVideoFile(uint id, uint type); - bool loadVGASoundFile(uint id, uint type); + void loadVGABeardFile(uint16 id); + void loadVGAVideoFile(uint16 id, uint8 type); + bool loadVGASoundFile(uint16 id, uint8 type); int init(); int go(); @@ -1146,11 +1151,12 @@ protected: virtual void animateSprites(); void dirtyClips(); + void dirtyClipCheck(int16 x, int16 y, int16 w, int16 h); void dirtyBackGround(); void restoreBackGround(); void saveBackGround(VgaSprite *vsp); - void clearSurfaces(uint num_lines); + void clearSurfaces(); void displayScreen(); void dumpVideoScript(const byte *src, bool one_opcode_only); @@ -1161,10 +1167,10 @@ protected: void dumpSingleBitmap(int file, int image, const byte *offs, int w, int h, byte base); void dumpBitmap(const char *filename, const byte *offs, int w, int h, int flags, const byte *palette, byte base); - void clearBackFromTop(uint lines); - void fillFrontFromBack(uint x, uint y, uint w, uint h); - void fillBackGroundFromBack(uint lines); - void fillBackFromFront(uint x, uint y, uint w, uint h); + void fillBackFromBackGround(uint16 height, uint16 width); + void fillBackFromFront(); + void fillBackGroundFromBack(); + void fillBackGroundFromFront(); virtual void doOutput(const byte *src, uint len); void clsCheck(WindowBlock *window); @@ -1184,10 +1190,13 @@ protected: void tidyIconArray(uint i); virtual void windowNewLine(WindowBlock *window); + void windowScroll(WindowBlock *window); void windowDrawChar(WindowBlock *window, uint x, uint y, byte chr); - void loadMusic(uint music); - void loadModule(uint music); + void loadMusic(uint16 track); + void playModule(uint16 music); + virtual void playMusic(uint16 music, uint16 track); + void stopMusic(); void checkTimerCallback(); void delay(uint delay); @@ -1202,12 +1211,12 @@ protected: void fastFadeIn(); void slowFadeIn(); - void vcStopAnimation(uint file, uint sprite); + virtual void vcStopAnimation(uint16 zone, uint16 sprite); + bool confirmOverWrite(WindowBlock *window); + int16 matchSaveGame(const char *name, uint16 max); void disableFileBoxes(); - virtual void listSaveGames(char *dst); virtual void userGame(bool load); - virtual int userGameGetKey(bool *b, char *buf, uint maxChar); void userGameBackSpace(WindowBlock *window, int x, byte b = 0); void fileError(WindowBlock *window, bool save_error); @@ -1275,8 +1284,6 @@ public: void oe1_bitSet(); void oe1_bitTest(); void oe1_zoneDisk(); - void oe1_saveUserGame(); - void oe1_loadUserGame(); void oe1_printStats(); void oe1_stopTune(); void oe1_printPlayerDamage(); @@ -1309,6 +1316,7 @@ public: void oe2_moveDirn(); void oe2_doClass(); void oe2_pObj(); + void oe2_loadGame(); void oe2_drawItem(); void oe2_doTable(); void oe2_pauseGame(); @@ -1347,6 +1355,7 @@ public: void oe2_b2Zero(); void oe2_b2NotZero(); + virtual void printStats(); protected: typedef void (AGOSEngine_Elvira2::*OpcodeProcElvira2) (); struct OpcodeEntryElvira2 { @@ -1356,12 +1365,14 @@ protected: const OpcodeEntryElvira2 *_opcodesElvira2; + virtual void readItemChildren(Common::SeekableReadStream *in, Item *item, uint tmp); + virtual bool loadGame(const char *filename, bool restartMode = false); virtual bool saveGame(uint slot, const char *caption); virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y); - virtual void addArrows(WindowBlock *window); + virtual void addArrows(WindowBlock *window, uint8 num); virtual uint setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *item_ptr); virtual void moveDirn(Item *i, uint x); @@ -1370,6 +1381,10 @@ protected: uint16 getExitState(Item *item, uint16 x, uint16 d); void setExitState(Item *i, uint16 n, uint16 d, uint16 s); void setSRExit(Item *i, int n, int d, uint16 s); + + virtual void listSaveGames(char *dst); + virtual void userGame(bool load); + virtual int userGameGetKey(bool *b, char *buf, uint maxChar); }; class AGOSEngine_Waxworks : public AGOSEngine_Elvira2 { @@ -1417,10 +1432,10 @@ protected: virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y); - virtual void addArrows(WindowBlock *window); + virtual void addArrows(WindowBlock *window, uint8 num); virtual uint setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *item_ptr); - virtual bool loadTablesIntoMem(uint subr_id); + virtual bool loadTablesIntoMem(uint16 subr_id); virtual void moveDirn(Item *i, uint x); }; @@ -1469,12 +1484,20 @@ protected: virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y); - virtual void addArrows(WindowBlock *window); + virtual void handleMouseMoved(); + + virtual void addArrows(WindowBlock *window, uint8 num); virtual uint setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *item_ptr); + virtual void playSpeech(uint16 speech_id, uint16 vga_sprite_id); + virtual void listSaveGames(char *dst); virtual void userGame(bool load); virtual int userGameGetKey(bool *b, char *buf, uint maxChar); + + virtual void playMusic(uint16 music, uint16 track); + + virtual void vcStopAnimation(uint16 zone, uint16 sprite); }; class AGOSEngine_Simon2 : public AGOSEngine_Simon1 { @@ -1511,8 +1534,10 @@ protected: virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y); - virtual void addArrows(WindowBlock *window); + virtual void addArrows(WindowBlock *window, uint8 num); virtual uint setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *item_ptr); + + virtual void playSpeech(uint16 speech_id, uint16 vga_sprite_id); }; class AGOSEngine_Feeble : public AGOSEngine_Simon2 { @@ -1582,7 +1607,7 @@ protected: void swapCharacterLogo(); virtual void timer_proc1(); - virtual void addArrows(WindowBlock *window); + virtual void addArrows(WindowBlock *window, uint8 num); virtual uint setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *item_ptr); virtual void resetVerbs(); @@ -1596,6 +1621,8 @@ protected: virtual void drawIconArray(uint i, Item *item_ptr, int line, int classMask); + virtual void colorWindow(WindowBlock *window); + virtual void doOutput(const byte *src, uint len); virtual void printScreenText(uint vga_sprite_id, uint color, const char *string_ptr, int16 x, int16 y, int16 width); @@ -1649,6 +1676,7 @@ public: void opp_sync(); void opp_saveUserGame(); void opp_loadUserGame(); + void opp_playTune(); void opp_saveOopsPosition(); void opp_resetGameTime(); void opp_resetPVCount(); diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index 1e1eaaf7e9..8748cff54e 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -30,6 +30,7 @@ #include "common/system.h" #include "graphics/cursorman.h" +#include "graphics/surface.h" #include "agos/animation.h" #include "agos/intern.h" @@ -44,6 +45,8 @@ MoviePlayer::MoviePlayer(AGOSEngine *vm, Audio::Mixer *mixer) : DXAPlayer(), _vm(vm), _mixer(mixer) { _omniTV = false; + _omniTVFile = 0; + _leftButtonDown = false; _rightButtonDown = false; @@ -103,25 +106,31 @@ bool MoviePlayer::load(const char *filename) { void MoviePlayer::playOmniTV() { // Load OmniTV video - if (!_fd.isOpen()) { - _vm->_variableArray[254] = 6747; - return; - } else { + if (_fd) { _vm->setBitFlag(42, false); _omniTV = true; startSound(); - return; + } else { + if (_omniTVFile) { + // Restore state + _fd = _omniTVFile; + _mixer->pauseHandle(_omniTVSound, false); + + _vm->setBitFlag(42, false); + _omniTV = true; + } else { + _vm->_variableArray[254] = 6747; + } } } void MoviePlayer::play() { - // The OmniTV videos were not included with Amiga and Macintosh versions. - if (_vm->getPlatform() == Common::kPlatformWindows && _vm->getBitFlag(40)) { + if (_vm->getBitFlag(40)) { playOmniTV(); return; } - if (!_fd.isOpen()) { + if (!_fd) { return; } @@ -132,7 +141,7 @@ void MoviePlayer::play() { // Resolution is smaller in Amiga verison so always clear screen if (_width == 384 && _height == 280) { - memset(_vm->_frontBuf, 0, _vm->_screenHeight * _vm->_screenWidth); + _vm->clearSurfaces(); } _ticks = _vm->_system->getMillis(); @@ -147,14 +156,15 @@ void MoviePlayer::play() { _vm->o_killAnimate(); if (_vm->getBitFlag(41)) { - memcpy(_vm->_backBuf, _vm->_frontBuf, _frameSize); + _vm->fillBackFromFront(); } else { uint8 palette[1024]; memset(palette, 0, sizeof(palette)); - _vm->clearSurfaces(480); + _vm->clearSurfaces(); _vm->_system->setPalette(palette, 0, 256); } + _vm->fillBackGroundFromBack(); _vm->_fastFadeOutFlag = true; } @@ -162,14 +172,14 @@ void MoviePlayer::startSound() { byte *buffer; uint32 offset, size, tag; - tag = _fd.readUint32BE(); + tag = _fd->readUint32BE(); if (tag == MKID_BE('WAVE')) { - size = _fd.readUint32BE(); + size = _fd->readUint32BE(); if (_sequenceNum) { Common::File in; - _fd.seek(size, SEEK_CUR); + _fd->seek(size, SEEK_CUR); in.open((const char *)"audio.wav"); if (!in.isOpen()) { @@ -186,7 +196,7 @@ void MoviePlayer::startSound() { in.close(); } else { buffer = (byte *)malloc(size); - _fd.read(buffer, size); + _fd->read(buffer, size); } Common::MemoryReadStream stream(buffer, size); @@ -197,8 +207,13 @@ void MoviePlayer::startSound() { } if (_bgSoundStream != NULL) { - _mixer->stopHandle(_bgSound); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSound, _bgSoundStream); + if (_omniTV) { + _mixer->stopHandle(_omniTVSound); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_omniTVSound, _bgSoundStream); + } else { + _mixer->stopHandle(_bgSound); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_bgSound, _bgSoundStream); + } } } @@ -207,8 +222,12 @@ void MoviePlayer::nextFrame() { return; if (_vm->getBitFlag(42)) { + // Save state + _omniTVFile = _fd; + _mixer->pauseHandle(_omniTVSound, true); + + _fd = 0; _omniTV = false; - closeFile(); return; } @@ -223,6 +242,7 @@ void MoviePlayer::nextFrame() { _frameNum++; } else { _omniTV = false; + _omniTVFile = 0; closeFile(); _vm->_variableArray[254] = 6747; } @@ -230,9 +250,8 @@ void MoviePlayer::nextFrame() { void MoviePlayer::handleNextFrame() { decodeNextFrame(); - processFrame(); - - _vm->_system->updateScreen(); + if (processFrame()) + _vm->_system->updateScreen(); _frameNum++; Common::Event event; @@ -285,9 +304,10 @@ void MoviePlayer::setPalette(byte *pal) { _vm->_system->setPalette(palette, 0, 256); } -void MoviePlayer::processFrame() { - copyFrameToBuffer(_vm->getFrontBuf(), (_vm->_screenWidth - _width) / 2, (_vm->_screenHeight - _height) / 2, _vm->_screenWidth); - _vm->_system->copyRectToScreen(_vm->getFrontBuf(), _vm->_screenWidth, 0, 0, _vm->_screenWidth, _vm->_screenHeight); +bool MoviePlayer::processFrame() { + Graphics::Surface *screen = _vm->_system->lockScreen(); + copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - _width) / 2, (_vm->_screenHeight - _height) / 2, _vm->_screenWidth); + _vm->_system->unlockScreen(); if ((_bgSoundStream == NULL) || ((int)(_mixer->getSoundElapsedTime(_bgSound) * _framesPerSec) / 1000 < _frameNum + 1) || _frameSkipped > _framesPerSec) { @@ -309,10 +329,13 @@ void MoviePlayer::processFrame() { while (_vm->_system->getMillis() < _ticks) _vm->_system->delayMillis(10); } - } else { - warning("dropped frame %i", _frameNum); - _frameSkipped++; + + return true; } + + warning("dropped frame %i", _frameNum); + _frameSkipped++; + return false; } const char * MoviePlayer::_sequenceList[90] = { diff --git a/engines/agos/animation.h b/engines/agos/animation.h index 07b2ebcd93..6776395ab7 100644 --- a/engines/agos/animation.h +++ b/engines/agos/animation.h @@ -44,6 +44,9 @@ class MoviePlayer : public Graphics::DXAPlayer { Audio::SoundHandle _bgSound; Audio::AudioStream *_bgSoundStream; + Audio::SoundHandle _omniTVSound; + Common::SeekableReadStream *_omniTVFile; + bool _omniTV; bool _leftButtonDown; bool _rightButtonDown; @@ -64,7 +67,7 @@ private: void playOmniTV(); void handleNextFrame(); - void processFrame(); + bool processFrame(); void startSound(); }; diff --git a/engines/agos/charset.cpp b/engines/agos/charset.cpp index 40b0a84390..9a37d90c33 100644 --- a/engines/agos/charset.cpp +++ b/engines/agos/charset.cpp @@ -25,9 +25,13 @@ #include "common/stdafx.h" +#include "common/system.h" + #include "agos/agos.h" #include "agos/intern.h" +#include "graphics/surface.h" + namespace AGOS { void AGOSEngine_Feeble::doOutput(const byte *src, uint len) { @@ -539,19 +543,7 @@ void AGOSEngine::justifyOutPut(byte chr) { doOutput(&chr, 1); clsCheck(_textWindow); } else if (chr == 0 || chr == ' ' || chr == 10) { - bool fit; - - // Note that in FF, _printCharCurPos may be greater than - // _printCharMaxPos. In Simon, that is probably prevented by - // testing if _printCharCurPos == _printCharMaxPos below. - - if (getGameType() == GType_FF || getGameType() == GType_PP) { - fit = _printCharMaxPos > _printCharCurPos + _printCharPixelCount; - } else { - fit = _printCharMaxPos - _printCharCurPos >= _printCharPixelCount; - } - - if (fit) { + if (_printCharMaxPos - _printCharCurPos >= _printCharPixelCount) { _printCharCurPos += _printCharPixelCount; doOutput(_lettersToPrintBuf, _numLettersToPrint); @@ -707,17 +699,48 @@ void AGOSEngine_Feeble::windowNewLine(WindowBlock *window) { void AGOSEngine::windowNewLine(WindowBlock *window) { window->textColumn = 0; - window->textColumnOffset = 0; + window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0; window->textLength = 0; if (window->textRow == window->height) { - // TODO - debug(0, "Window Scroll"); + if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || + getGameType() == GType_WW) { + windowScroll(window); + } } else { window->textRow++; } } +void AGOSEngine::windowScroll(WindowBlock *window) { + _lockWord |= 0x8000; + + if (window->height != 1) { + Graphics::Surface *screen = _system->lockScreen(); + + byte *src, *dst; + uint16 w, h; + + w = window->width * 8; + h = (window->height -1) * 8; + + dst = (byte *)screen->pixels + window->y * _screenWidth + window->x * 8; + src = dst + 8 * _screenWidth; + + do { + memcpy(dst, src, w); + src += _screenWidth; + dst += _screenWidth; + } while (--h); + + _system->unlockScreen(); + } + + colorBlock(window, window->x * 8, (window->height - 1) * 8 + window->y, window->width * 8, 8); + + _lockWord &= ~0x8000; +} + #ifdef PALMOS_68K static const byte *feeble_windowFont; static const byte *czech_simonFont; @@ -729,6 +752,8 @@ static const byte *hebrew_simonFont; static const byte *italian_simonFont; static const byte *spanish_simonFont; static const byte *english_simonFont; +static const byte *spanish_commonFont; +static const byte *italian_commonFont; static const byte *french_commonFont; static const byte *english_commonFont; #else @@ -1839,6 +1864,208 @@ static const byte english_simonFont[] = { 240, 240, 240, 240, 240, 240, 240, 240, }; +static const byte spanish_commonFont[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, + 0x00, 0x50, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x90, 0x00, 0x60, 0x90, 0x90, 0x68, 0x00, + 0x00, 0x90, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, + 0x00, 0x90, 0x00, 0x90, 0x90, 0x90, 0x60, 0x00, + 0x00, 0x10, 0x28, 0x10, 0x2A, 0x44, 0x3A, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00, + 0x00, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, + 0x00, 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, 0x00, + 0x00, 0x70, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x10, 0x20, 0x00, 0x78, 0x70, 0x40, 0x38, 0x00, + 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, + 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, + 0x00, 0x70, 0x88, 0x10, 0x20, 0x48, 0xF8, 0x00, + 0x00, 0x70, 0x88, 0x30, 0x08, 0x88, 0x70, 0x00, + 0x00, 0x10, 0x20, 0x40, 0x90, 0xF8, 0x10, 0x00, + 0x00, 0xF8, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, + 0x00, 0x70, 0x88, 0x80, 0xF0, 0x88, 0x70, 0x00, + 0x00, 0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, + 0x00, 0x70, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, + 0x00, 0x70, 0x88, 0x78, 0x08, 0x88, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, + 0x20, 0x40, 0x00, 0x60, 0x90, 0x90, 0x68, 0x00, + 0x20, 0x40, 0x00, 0x60, 0x20, 0x28, 0x30, 0x00, + 0x20, 0x40, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, + 0x20, 0x40, 0x00, 0x98, 0x90, 0x90, 0xE8, 0x00, + 0x00, 0x3C, 0x42, 0x04, 0x08, 0x00, 0x08, 0x00, + 0x28, 0x50, 0x00, 0xD8, 0x68, 0x48, 0x48, 0x00, + 0x20, 0x50, 0x50, 0x70, 0x50, 0x50, 0x88, 0x00, + 0xF0, 0x48, 0x48, 0x70, 0x48, 0x48, 0xF0, 0x00, + 0x30, 0x48, 0x80, 0x80, 0x80, 0x48, 0x30, 0x00, + 0xF0, 0x48, 0x48, 0x48, 0x48, 0x48, 0xF0, 0x00, + 0xF8, 0x40, 0x40, 0x70, 0x40, 0x40, 0xF8, 0x00, + 0xF8, 0x40, 0x40, 0x70, 0x40, 0x40, 0xE0, 0x00, + 0x38, 0x40, 0x80, 0x98, 0x88, 0x48, 0x30, 0x00, + 0xC8, 0x48, 0x48, 0x78, 0x48, 0x48, 0xC8, 0x00, + 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, + 0x78, 0x10, 0x10, 0x10, 0x90, 0x90, 0x60, 0x00, + 0xC8, 0x50, 0x60, 0x40, 0x60, 0x50, 0xC8, 0x00, + 0xE0, 0x40, 0x40, 0x40, 0x40, 0x48, 0xF8, 0x00, + 0x88, 0xD8, 0xA8, 0x88, 0x88, 0x88, 0x88, 0x00, + 0xC8, 0x48, 0x68, 0x58, 0x58, 0x48, 0xC8, 0x00, + 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, + 0xF0, 0x48, 0x48, 0x70, 0x40, 0x40, 0xC0, 0x00, + 0x60, 0x90, 0x90, 0x90, 0xB0, 0x90, 0x68, 0x00, + 0xF0, 0x48, 0x48, 0x70, 0x50, 0x48, 0xC8, 0x00, + 0x70, 0x88, 0x80, 0x60, 0x10, 0x88, 0x70, 0x00, + 0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, + 0x88, 0x50, 0x50, 0x50, 0x50, 0x50, 0x20, 0x00, + 0x88, 0x88, 0x88, 0x50, 0x50, 0x50, 0x20, 0x00, + 0x88, 0x88, 0x88, 0x88, 0xA8, 0xD8, 0x88, 0x00, + 0x88, 0x50, 0x70, 0x20, 0x70, 0x50, 0x88, 0x00, + 0x88, 0x48, 0x30, 0x20, 0x40, 0x80, 0xC0, 0x00, + 0xF8, 0x88, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, + 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x0E, 0x00, + 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, + 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, + 0x00, 0x20, 0x00, 0x20, 0x40, 0x88, 0x70, 0x00, + 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, + 0x00, 0x90, 0x00, 0x90, 0x90, 0x90, 0x60, 0x00, + 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x68, 0x00, + 0x40, 0x40, 0x50, 0x68, 0x48, 0x48, 0xF0, 0x00, + 0x00, 0x00, 0x30, 0x48, 0x40, 0x48, 0x30, 0x00, + 0x10, 0x10, 0x70, 0x90, 0x90, 0x90, 0x68, 0x00, + 0x00, 0x00, 0x70, 0x48, 0x70, 0x40, 0x38, 0x00, + 0x10, 0x38, 0x20, 0x70, 0x20, 0x20, 0x20, 0x40, + 0x00, 0x00, 0x78, 0x90, 0x90, 0x90, 0x70, 0x10, + 0xC0, 0x40, 0x58, 0x68, 0x48, 0x48, 0xC8, 0x00, + 0x20, 0x00, 0x60, 0x20, 0x20, 0x28, 0x30, 0x00, + 0x10, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x60, + 0x40, 0x40, 0x70, 0x48, 0x70, 0x50, 0xC8, 0x00, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x60, 0x00, + 0x00, 0x00, 0xA8, 0xF8, 0xA8, 0xA8, 0xA8, 0x00, + 0x00, 0x00, 0xD8, 0x68, 0x48, 0x48, 0x48, 0x00, + 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x00, + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x40, 0xC0, + 0x00, 0x00, 0x70, 0x90, 0x90, 0x70, 0x18, 0x10, + 0x00, 0x00, 0xD8, 0x68, 0x40, 0x40, 0xE0, 0x00, + 0x00, 0x00, 0x38, 0x40, 0x30, 0x08, 0x70, 0x00, + 0x20, 0x20, 0x70, 0x20, 0x20, 0x28, 0x30, 0x00, + 0x00, 0x00, 0x98, 0x90, 0x90, 0x90, 0xE8, 0x00, + 0x00, 0x00, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, + 0x00, 0x00, 0xA8, 0xA8, 0xA8, 0xF8, 0xA8, 0x00, + 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, + 0x00, 0x00, 0x98, 0x90, 0x90, 0x70, 0x10, 0x60, + 0x00, 0x00, 0x78, 0x10, 0x20, 0x40, 0x78, 0x00, + 0x20, 0x50, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, + 0x00, 0x0E, 0x08, 0x30, 0x08, 0x08, 0x0E, 0x00, + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, + 0x00, 0x70, 0x10, 0x0C, 0x10, 0x10, 0x70, 0x00, + 0x00, 0x14, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, +}; + +static const byte italian_commonFont[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, + 0x00, 0x50, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x90, 0x00, 0x60, 0x90, 0x90, 0x68, 0x00, + 0x00, 0x90, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, + 0x40, 0x20, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, + 0x00, 0x10, 0x28, 0x10, 0x2A, 0x44, 0x3A, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00, + 0x00, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, + 0x00, 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, 0x00, + 0x40, 0x20, 0x00, 0x60, 0x20, 0x28, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x10, 0x20, 0x00, 0x78, 0x70, 0x40, 0x38, 0x00, + 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, + 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, + 0x00, 0x70, 0x88, 0x10, 0x20, 0x48, 0xF8, 0x00, + 0x00, 0x70, 0x88, 0x30, 0x08, 0x88, 0x70, 0x00, + 0x00, 0x10, 0x20, 0x40, 0x90, 0xF8, 0x10, 0x00, + 0x00, 0xF8, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, + 0x00, 0x70, 0x88, 0x80, 0xF0, 0x88, 0x70, 0x00, + 0x00, 0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, + 0x00, 0x70, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, + 0x00, 0x70, 0x88, 0x78, 0x08, 0x88, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, + 0x40, 0x20, 0x00, 0x60, 0x90, 0x90, 0x68, 0x00, + 0x40, 0x20, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, + 0x20, 0x10, 0x00, 0x78, 0x70, 0x40, 0x38, 0x00, + 0x20, 0x50, 0x00, 0x78, 0x70, 0x40, 0x38, 0x00, + 0x00, 0x3C, 0x42, 0x04, 0x08, 0x00, 0x08, 0x00, + 0x20, 0x50, 0x00, 0x60, 0x20, 0x28, 0x30, 0x00, + 0x20, 0x50, 0x50, 0x70, 0x50, 0x50, 0x88, 0x00, + 0xF0, 0x48, 0x48, 0x70, 0x48, 0x48, 0xF0, 0x00, + 0x30, 0x48, 0x80, 0x80, 0x80, 0x48, 0x30, 0x00, + 0xF0, 0x48, 0x48, 0x48, 0x48, 0x48, 0xF0, 0x00, + 0xF8, 0x40, 0x40, 0x70, 0x40, 0x40, 0xF8, 0x00, + 0xF8, 0x40, 0x40, 0x70, 0x40, 0x40, 0xE0, 0x00, + 0x38, 0x40, 0x80, 0x98, 0x88, 0x48, 0x30, 0x00, + 0xC8, 0x48, 0x48, 0x78, 0x48, 0x48, 0xC8, 0x00, + 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, + 0x78, 0x10, 0x10, 0x10, 0x90, 0x90, 0x60, 0x00, + 0xC8, 0x50, 0x60, 0x40, 0x60, 0x50, 0xC8, 0x00, + 0xE0, 0x40, 0x40, 0x40, 0x40, 0x48, 0xF8, 0x00, + 0x88, 0xD8, 0xA8, 0x88, 0x88, 0x88, 0x88, 0x00, + 0xC8, 0x48, 0x68, 0x58, 0x58, 0x48, 0xC8, 0x00, + 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, + 0xF0, 0x48, 0x48, 0x70, 0x40, 0x40, 0xC0, 0x00, + 0x60, 0x90, 0x90, 0x90, 0xB0, 0x90, 0x68, 0x00, + 0xF0, 0x48, 0x48, 0x70, 0x50, 0x48, 0xC8, 0x00, + 0x70, 0x88, 0x80, 0x60, 0x10, 0x88, 0x70, 0x00, + 0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, + 0x88, 0x50, 0x50, 0x50, 0x50, 0x50, 0x20, 0x00, + 0x88, 0x88, 0x88, 0x50, 0x50, 0x50, 0x20, 0x00, + 0x88, 0x88, 0x88, 0x88, 0xA8, 0xD8, 0x88, 0x00, + 0x88, 0x50, 0x70, 0x20, 0x70, 0x50, 0x88, 0x00, + 0x88, 0x48, 0x30, 0x20, 0x40, 0x80, 0xC0, 0x00, + 0xF8, 0x88, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, + 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x0E, 0x00, + 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, + 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, + 0x00, 0x30, 0x48, 0x40, 0x48, 0x30, 0x10, 0x30, + 0x00, 0x50, 0x00, 0x60, 0x20, 0x28, 0x30, 0x00, + 0x20, 0x10, 0x00, 0x98, 0x90, 0x90, 0xE8, 0x00, + 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x68, 0x00, + 0x40, 0x40, 0x50, 0x68, 0x48, 0x48, 0xF0, 0x00, + 0x00, 0x00, 0x30, 0x48, 0x40, 0x48, 0x30, 0x00, + 0x10, 0x10, 0x70, 0x90, 0x90, 0x90, 0x68, 0x00, + 0x00, 0x00, 0x70, 0x48, 0x70, 0x40, 0x38, 0x00, + 0x10, 0x38, 0x20, 0x70, 0x20, 0x20, 0x20, 0x40, + 0x00, 0x00, 0x78, 0x90, 0x90, 0x90, 0x70, 0x10, + 0xC0, 0x40, 0x58, 0x68, 0x48, 0x48, 0xC8, 0x00, + 0x20, 0x00, 0x60, 0x20, 0x20, 0x28, 0x30, 0x00, + 0x10, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x60, + 0x40, 0x40, 0x70, 0x48, 0x70, 0x50, 0xC8, 0x00, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x60, 0x00, + 0x00, 0x00, 0xA8, 0xF8, 0xA8, 0xA8, 0xA8, 0x00, + 0x00, 0x00, 0xD8, 0x68, 0x48, 0x48, 0x48, 0x00, + 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x00, + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x40, 0xC0, + 0x00, 0x00, 0x70, 0x90, 0x90, 0x70, 0x18, 0x10, + 0x00, 0x00, 0xD8, 0x68, 0x40, 0x40, 0xE0, 0x00, + 0x00, 0x00, 0x38, 0x40, 0x30, 0x08, 0x70, 0x00, + 0x20, 0x20, 0x70, 0x20, 0x20, 0x28, 0x30, 0x00, + 0x00, 0x00, 0x98, 0x90, 0x90, 0x90, 0xE8, 0x00, + 0x00, 0x00, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, + 0x00, 0x00, 0xA8, 0xA8, 0xA8, 0xF8, 0xA8, 0x00, + 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, + 0x00, 0x00, 0x98, 0x90, 0x90, 0x70, 0x10, 0x60, + 0x00, 0x00, 0x78, 0x10, 0x20, 0x40, 0x78, 0x00, + 0x20, 0x50, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, + 0x00, 0x0E, 0x08, 0x30, 0x08, 0x08, 0x0E, 0x00, + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, + 0x00, 0x70, 0x10, 0x0C, 0x10, 0x10, 0x70, 0x00, + 0x00, 0x14, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, +}; + static const byte french_commonFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, @@ -2052,14 +2279,16 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { _lockWord |= 0x8000; - dst = getFrontBuf() + y * _dxSurfacePitch + x + window->textColumnOffset; + Graphics::Surface *screen = _system->lockScreen(); if (getGameType() == GType_FF || getGameType() == GType_PP) { + dst = getBackGround() + y * _dxSurfacePitch + x + window->textColumnOffset; h = 13; w = feebleFontSize[chr - 0x20]; src = feeble_windowFont + (chr - 0x20) * 13; } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { + dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset; h = 8; w = 6; @@ -2095,13 +2324,17 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { error("windowDrawChar: Unknown language %d\n", _language); } } else { + dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset; h = 8; w = 6; - // TODO: Add font tables for German and Spanish + // TODO: Add font tables for German switch (_language) { case Common::ES_ESP: - src = english_commonFont + (chr - 0x20) * 8; + src = spanish_commonFont + (chr - 0x20) * 8; + break; + case Common::IT_ITA: + src = italian_commonFont + (chr - 0x20) * 8; break; case Common::FR_FRA: src = french_commonFont + (chr - 0x20) * 8; @@ -2139,6 +2372,8 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { dst += _dxSurfacePitch; } while (--h); + _system->unlockScreen(); + _lockWord &= ~0x8000; } diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp index c43e243bf3..35bb8ea216 100644 --- a/engines/agos/cursor.cpp +++ b/engines/agos/cursor.cpp @@ -380,7 +380,7 @@ void AGOSEngine_PuzzlePack::handleMouseMoved() { drawMousePointer(); } -void AGOSEngine::handleMouseMoved() { +void AGOSEngine_Simon1::handleMouseMoved() { uint x; if (_mouseHideCount) { @@ -399,13 +399,6 @@ void AGOSEngine::handleMouseMoved() { resetVerbs(); } - if (_leftButton == 0) { - if (_dragMode != 0) { - _dragEnd = 1; - } - _dragCount = 0; - } - if (getGameType() == GType_FF) { if (getBitFlag(99)) { // Oracle if (_mouse.x >= 10 && _mouse.x <= 635 && _mouse.y >= 5 && _mouse.y <= 475) { @@ -449,7 +442,50 @@ void AGOSEngine::handleMouseMoved() { get_out2:; _vgaVar9 = 0; } - } else if (getGameType() == GType_WW) { + } + + if (_mouse != _mouseOld) + _needHitAreaRecalc++; + + if (_leftButtonOld == 0 && _leftButtonCount != 0) { + boxController(_mouse.x, _mouse.y, 3); + } + _leftButtonOld = _leftButton; + + x = 0; + if (_lastHitArea3 == 0 && _leftButtonDown != 0) { + _leftButtonDown = 0; + x = 1; + } else { + if (_litBoxFlag == 0 && _needHitAreaRecalc == 0) + goto get_out; + } + + boxController(_mouse.x, _mouse.y, x); + _lastHitArea3 = _lastHitArea; + if (x == 1 && _lastHitArea == NULL) + _lastHitArea3 = (HitArea *) -1; + +get_out: + _mouseOld = _mouse; + drawMousePointer(); + + _needHitAreaRecalc = 0; + _litBoxFlag = 0; +} + +void AGOSEngine::handleMouseMoved() { + uint x; + + if (_mouseHideCount) { + CursorMan.showMouse(false); + return; + } + + CursorMan.showMouse(true); + _mouse = _eventMan->getMousePos(); + + if (getGameType() == GType_WW) { if (_variableArray[51] != 0 && _mouseCursor != _variableArray[51]) { _mouseCursor = _variableArray[51]; _needHitAreaRecalc++; @@ -466,10 +502,20 @@ void AGOSEngine::handleMouseMoved() { } } + if (_leftClick == true) { + _leftClick = false; + if (_dragMode != 0) { + _dragEnd = 1; + } else { + _oneClick = true; + } + _dragCount = 0; + } + if (_mouse != _mouseOld) _needHitAreaRecalc++; - if (_leftButtonOld == 0 && _leftButtonCount != 0) { + if (_leftButtonOld == 0 && _leftButton != 0) { _lastClickRem = 0; boxController(_mouse.x, _mouse.y, 3); } @@ -493,8 +539,8 @@ void AGOSEngine::handleMouseMoved() { } x = 0; - if (_lastHitArea3 == 0 && _leftButtonDown != 0) { - _leftButtonDown = 0; + if (_oneClick == true) { + _oneClick = false; x = 1; } else { if (_litBoxFlag == 0 && _needHitAreaRecalc == 0) @@ -504,11 +550,7 @@ void AGOSEngine::handleMouseMoved() { boxstuff: boxController(_mouse.x, _mouse.y, x); _lastHitArea3 = _lastHitArea; - if (x == 1 && _lastHitArea == NULL) - _lastHitArea3 = (HitArea *) -1; - get_out: - _mouseOld = _mouse; drawMousePointer(); diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp index 7a455fa0f9..ce50460621 100644 --- a/engines/agos/debugger.cpp +++ b/engines/agos/debugger.cpp @@ -83,13 +83,17 @@ bool Debugger::Cmd_DebugLevel(int argc, const char **argv) { bool Debugger::Cmd_PlayMusic(int argc, const char **argv) { if (argc > 1) { uint music = atoi(argv[1]); - uint range = (_vm->getGameType() == GType_SIMON2) ? 93 : 34; - if (music <= range) { - _vm->loadMusic(music); - if (_vm->getGameType() == GType_SIMON2) + if (music <= _vm->_numMusic) { + if (_vm->getGameType() == GType_PP) { + // TODO + } else if (_vm->getGameType() == GType_SIMON2) { + _vm->loadMusic(music); _vm->_midi.startTrack(0); + } else { + _vm->playMusic(music, 0); + } } else - DebugPrintf("Music out of range (0 - %d)\n", range); + DebugPrintf("Music out of range (0 - %d)\n", _vm->_numMusic); } else DebugPrintf("Syntax: music <musicnum>\n"); @@ -99,11 +103,10 @@ bool Debugger::Cmd_PlayMusic(int argc, const char **argv) { bool Debugger::Cmd_PlaySound(int argc, const char **argv) { if (argc > 1) { uint sound = atoi(argv[1]); - uint range = (_vm->getGameType() == GType_SIMON2) ? 222 : 127; - if (sound <= range) + if (sound <= _vm->_numSFX) _vm->_sound->playEffects(sound); else - DebugPrintf("Sound out of range (0 - %d)\n", range); + DebugPrintf("Sound out of range (0 - %d)\n", _vm->_numSFX); } else DebugPrintf("Syntax: sound <soundnum>\n"); @@ -113,11 +116,10 @@ bool Debugger::Cmd_PlaySound(int argc, const char **argv) { bool Debugger::Cmd_PlayVoice(int argc, const char **argv) { if (argc > 1) { uint voice = atoi(argv[1]); - uint range = (_vm->getGameType() == GType_SIMON2) ? 3632 : 1996; - if (voice <= range) + if (voice <= _vm->_numSpeech) _vm->_sound->playVoice(voice); else - DebugPrintf("Voice out of range (0 - %d)\n", range); + DebugPrintf("Voice out of range (0 - %d)\n", _vm->_numSpeech); } else DebugPrintf("Syntax: voice <voicenum>\n"); diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index dbb4c8faf1..0f5aa2768a 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -106,7 +106,7 @@ GameList Engine_AGOS_gameIDList() { } GameDescriptor Engine_AGOS_findGameID(const char *gameid) { - return Common::AdvancedDetector::findGameID(gameid, detectionParams); + return Common::AdvancedDetector::findGameID(gameid, simonGames, obsoleteGameIDsTable); } GameList Engine_AGOS_detectGames(const FSList &fslist) { @@ -117,7 +117,8 @@ PluginError Engine_AGOS_create(OSystem *syst, Engine **engine) { assert(engine); const char *gameid = ConfMan.get("gameid").c_str(); - //const AGOSGameDescription gd = (const AGOSGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); + //Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); + //const AGOSGameDescription *gd = (const AGOSGameDescription *)(encapsulatedDesc.realDesc); //if (gd == 0) { // return kNoGameDataFoundError; //} @@ -154,7 +155,9 @@ REGISTER_PLUGIN(AGOS, "AGOS", "AGOS (C) Adventure Soft"); namespace AGOS { bool AGOSEngine::initGame() { - _gameDescription = (const AGOSGameDescription *)Common::AdvancedDetector::detectBestMatchingGame(detectionParams); + Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams); + _gameDescription = (const AGOSGameDescription *)(encapsulatedDesc.realDesc); + return (_gameDescription != 0); } diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h index cfb795efbd..cb6123dc54 100644 --- a/engines/agos/detection_tables.h +++ b/engines/agos/detection_tables.h @@ -56,7 +56,6 @@ static const AGOSGameDescription gameDescriptions[] = { { { "gameamiga", GAME_BASEFILE, "7bdaff4a118d8035047cf9b1393b3fa0", -1}, { "icon.dat", GAME_ICONFILE, "2db931e84f1ca01f0816dddfae3f49e1", -1}, - { "start", GAME_RESTFILE, "c111be88c7f6d40e3f9b128939c1236d", -1}, { NULL, 0, NULL, 0} }, Common::EN_ANY, @@ -69,6 +68,46 @@ static const AGOSGameDescription gameDescriptions[] = { GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR }, + // Elvira 1 - French Amiga Floppy + { + { + "elvira1", + "Floppy", + { + { "gameamiga", GAME_BASEFILE, "ab1a0798f74e71cc58a06e7e0db6f8a7", -1}, + { "icon.dat", GAME_ICONFILE, "2db931e84f1ca01f0816dddfae3f49e1", -1}, + { NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformAmiga, + Common::ADGF_NO_FLAGS + }, + + GType_ELVIRA1, + GID_ELVIRA1, + GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR + }, + + // Elvira 1 - German Amiga Floppy + { + { + "elvira1", + "Floppy", + { + { "gameamiga", GAME_BASEFILE, "bde0334344c7b3a278ccc9a300f3085c", -1}, + { "icon.dat", GAME_ICONFILE, "2db931e84f1ca01f0816dddfae3f49e1", -1}, + { NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformAmiga, + Common::ADGF_NO_FLAGS + }, + + GType_ELVIRA1, + GID_ELVIRA1, + GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR + }, + // Elvira 1 - English Atari ST Floppy Demo { { @@ -100,7 +139,6 @@ static const AGOSGameDescription gameDescriptions[] = { { { "gamest", GAME_BASEFILE, "8942859018fcfb2dbed13e83d974d1ab", -1}, { "icon.dat", GAME_ICONFILE, "2db931e84f1ca01f0816dddfae3f49e1", -1}, - { "start", GAME_RESTFILE, "cd711028e209c47b81d04141fff2587b", -1}, { "tbllist", GAME_TBLFILE, "5b6ff494bf7e24213758598ef4ac0a8b", -1}, { NULL, 0, NULL, 0} }, @@ -123,7 +161,6 @@ static const AGOSGameDescription gameDescriptions[] = { { { "gamest", GAME_BASEFILE, "ce2100ba71284f55ac302847d7f94747", -1}, { "icon.dat", GAME_ICONFILE, "2db931e84f1ca01f0816dddfae3f49e1", -1}, - { "start", GAME_RESTFILE, "cd711028e209c47b81d04141fff2587b", -1}, { "tbllist", GAME_TBLFILE, "5b6ff494bf7e24213758598ef4ac0a8b", -1}, { NULL, 0, NULL, 0} }, @@ -146,7 +183,6 @@ static const AGOSGameDescription gameDescriptions[] = { { { "gamepc", GAME_BASEFILE, "a49e132a1f18306dd5d1ec2fe435e178", -1}, { "icon.dat", GAME_ICONFILE, "fda48c9da7f3e72d0313e2f5f760fc45", -1}, - { "start", GAME_RESTFILE, "69fb4f12108b39ae659f108cad4d3efe", -1}, { "tbllist", GAME_TBLFILE, "319f6b227c7822a551f57d24e70f8149", -1}, { NULL, 0, NULL, 0} }, @@ -160,20 +196,19 @@ static const AGOSGameDescription gameDescriptions[] = { GF_OLD_BUNDLE }, - // Elvira 1 - German DOS Floppy + // Elvira 1 - French DOS Floppy { { "elvira1", "Floppy", { - { "gamepc", GAME_BASEFILE, "d0b593143e21fc150c044819df2c0b98", -1}, + { "gamepc", GAME_BASEFILE, "9076d507d60cc454df662316438ec843", -1}, { "icon.dat", GAME_ICONFILE, "fda48c9da7f3e72d0313e2f5f760fc45", -1}, - { "start", GAME_RESTFILE, "69fb4f12108b39ae659f108cad4d3efe", -1}, { "tbllist", GAME_TBLFILE, "319f6b227c7822a551f57d24e70f8149", -1}, { NULL, 0, NULL, 0} }, - Common::DE_DEU, + Common::FR_FRA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, @@ -183,20 +218,19 @@ static const AGOSGameDescription gameDescriptions[] = { GF_OLD_BUNDLE }, - // Elvira 1 - French DOS Floppy + // Elvira 1 - German DOS Floppy { { "elvira1", "Floppy", { - { "gamepc", GAME_BASEFILE, "9076d507d60cc454df662316438ec843", -1}, + { "gamepc", GAME_BASEFILE, "d0b593143e21fc150c044819df2c0b98", -1}, { "icon.dat", GAME_ICONFILE, "fda48c9da7f3e72d0313e2f5f760fc45", -1}, - { "start", GAME_RESTFILE, "69fb4f12108b39ae659f108cad4d3efe", -1}, { "tbllist", GAME_TBLFILE, "319f6b227c7822a551f57d24e70f8149", -1}, { NULL, 0, NULL, 0} }, - Common::FR_FRA, + Common::DE_DEU, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, @@ -256,6 +290,31 @@ static const AGOSGameDescription gameDescriptions[] = { GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR }, + // Elvira 2 - Italian Amiga Floppy + { + { + "elvira2", + "Floppy", + + { + { "gameamiga", GAME_BASEFILE, "3d4e0c8da4ebd222e50de2dffed92955", -1}, + { "icon.dat", GAME_ICONFILE, "a88b1c02e13ab04dd790ec30502c323d", -1}, + { "menus.dat", GAME_MENUFILE, "a2fdc88a77c8bdffec6b36cbeda4d955", -1}, + { "start", GAME_RESTFILE, "a9f876c6c66dfd011b971da3dc7b4ada", -1}, + { "stripped.txt", GAME_STRFILE, "41c975a9c1106cb5298a0bc3df0a266e", -1}, + { "tbllist", GAME_TBLFILE, "177f5f2640e80ef92d1421d32de06a5e", -1}, + { NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformAmiga, + Common::ADGF_NO_FLAGS + }, + + GType_ELVIRA2, + GID_ELVIRA2, + GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR + }, + // Elvira 2 - English Atari ST Floppy { { @@ -357,6 +416,31 @@ static const AGOSGameDescription gameDescriptions[] = { GF_OLD_BUNDLE }, + // Elvira 2 - French DOS Floppy + { + { + "elvira2", + "Floppy", + + { + { "gamepc", GAME_BASEFILE, "4bf28ab00f5324fd938e632595742382", -1}, + { "icon.dat", GAME_ICONFILE, "83a7278bff55c82fbb3aef92981866c9", -1}, + { "menus.dat", GAME_MENUFILE, "a2fdc88a77c8bdffec6b36cbeda4d955", -1}, + { "start", GAME_RESTFILE, "4d380a35ba941d03ee5084c71d20055b", -1}, + { "stripped.txt", GAME_STRFILE, "c3a8f644551a27c8a2fec0f8070b46b7", -1}, + { "tbllist", GAME_TBLFILE, "8252660df0edbdbc3e6377e155bbd0c5", -1}, + { NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + + GType_ELVIRA2, + GID_ELVIRA2, + GF_OLD_BUNDLE + }, + // Elvira 2 - German DOS Floppy { { @@ -382,22 +466,22 @@ static const AGOSGameDescription gameDescriptions[] = { GF_OLD_BUNDLE }, - // Elvira 2 - French DOS Floppy + // Elvira 2 - Italian DOS Floppy { { "elvira2", "Floppy", { - { "gamepc", GAME_BASEFILE, "4bf28ab00f5324fd938e632595742382", -1}, + { "gamepc", GAME_BASEFILE, "09a3f1087f2977ff462ad2417bde0a5c", -1}, { "icon.dat", GAME_ICONFILE, "83a7278bff55c82fbb3aef92981866c9", -1}, { "menus.dat", GAME_MENUFILE, "a2fdc88a77c8bdffec6b36cbeda4d955", -1}, - { "start", GAME_RESTFILE, "4d380a35ba941d03ee5084c71d20055b", -1}, + { "start", GAME_RESTFILE, "016107aced82d0cc5d758a9fba716270", -1}, { "stripped.txt", GAME_STRFILE, "c3a8f644551a27c8a2fec0f8070b46b7", -1}, { "tbllist", GAME_TBLFILE, "8252660df0edbdbc3e6377e155bbd0c5", -1}, { NULL, 0, NULL, 0} }, - Common::FR_FRA, + Common::IT_ITA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, @@ -443,7 +527,6 @@ static const AGOSGameDescription gameDescriptions[] = { { "icon.pkd", GAME_ICONFILE, "4822a91c18b1b2005ac17fc617f7dcbe", -1}, { "menus.dat", GAME_MENUFILE, "3409eeb8ca8b46fc04da99de67573f5e", -1}, { "start", GAME_RESTFILE, "b575b336e741dde1725edd4079d5ab67", -1}, - { "statelst", GAME_STATFILE, "469e98c69f00928a8366ba415d91902d", -1}, { "stripped.txt", GAME_STRFILE, "6faaebff2786216900061eeb978f10af", -1}, { "tbllist", GAME_TBLFILE, "95c44bfc380770a6b6dd0dfcc69e80a0", -1}, { "xtbllist", GAME_XTBLFILE, "6c7b3db345d46349a5226f695c03e20f", -1}, diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp index f5f7161805..bb28da73b5 100644 --- a/engines/agos/draw.cpp +++ b/engines/agos/draw.cpp @@ -27,22 +27,16 @@ #include "common/system.h" +#include "graphics/surface.h" + #include "agos/agos.h" #include "agos/intern.h" namespace AGOS { -byte *AGOSEngine::getFrontBuf() { - if (getGameType() != GType_PP && getGameType() != GType_FF) - _updateScreen = true; - - _dxSurfacePitch = _screenWidth; - return _frontBuf; -} - byte *AGOSEngine::getBackBuf() { _dxSurfacePitch = _screenWidth; - return _useBackGround ? _backGroundBuf : _backBuf; + return _backBuf; } byte *AGOSEngine::getBackGround() { @@ -166,27 +160,29 @@ void AGOSEngine::animateSprites() { _vgaSpriteChanged++; } - if ((getGameType() == GType_ELVIRA1 && !_variableArray[293] || - getGameType() == GType_ELVIRA2 && !_variableArray[71]) && - _wallOn) { + if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) { + const uint8 var = (getGameType() == GType_ELVIRA1) ? 293 : 71; + if (_wallOn && !_variableArray[var]) { + _wallOn--; - VC10_state state; - state.srcPtr = getBackGround() + 504; - state.height = 127; - state.width = 14; - state.y = 0; - state.x = 0; - state.palette = 0; - state.paletteMod = 0; - state.flags = kDFNonTrans; + VC10_state state; + state.srcPtr = getBackGround() + 3 * _screenWidth + 3 * 16; + state.height = state.draw_height = 127; + state.width = state.draw_width = 14; + state.y = 0; + state.x = 0; + state.palette = 0; + state.paletteMod = 0; + state.flags = kDFNonTrans; - _windowNum = 4; + _windowNum = 4; - _backFlag = 1; - drawImage(&state); - _backFlag = 0; + _backFlag = 1; + drawImage(&state); + _backFlag = 0; - _vgaSpriteChanged++; + _vgaSpriteChanged++; + } } if (!_scrollFlag && !_vgaSpriteChanged) { @@ -209,7 +205,12 @@ void AGOSEngine::animateSprites() { restoreBackGround(); vsp = _vgaSprites; - while (vsp->id) { + for (; vsp->id !=0; vsp++) { + if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) && + !(vsp->windowNum & 0x8000)) { + continue; + } + vsp->windowNum &= 0x7FFF; vpe = &_vgaBufferPointers[vsp->zoneNum]; @@ -223,10 +224,10 @@ void AGOSEngine::animateSprites() { saveBackGround(vsp); drawImage_init(vsp->image, vsp->palette, vsp->x, vsp->y, vsp->flags); - vsp++; } if (getGameType() == GType_ELVIRA1 && _variableArray[293]) { + // Used by the Fire Wall and Ice Wall spells debug(0, "Using special wall"); uint8 color, h, len; @@ -256,10 +257,9 @@ void AGOSEngine::animateSprites() { } _window4Flag = 1; - setMoveRect(0, 224, 0, 127); + setMoveRect(0, 0, 224, 127); } else if (getGameType() == GType_ELVIRA2 && _variableArray[71] & 2) { - debug(0, "Using special wall"); - + // Used by the Unholy Barrier spell uint8 color, h, len; byte *dst = _window4BackScn; @@ -284,14 +284,14 @@ void AGOSEngine::animateSprites() { while (len--) { dst += 2; *dst++ = color; - dst++; + dst += 1; } dst += 448; h--; } _window4Flag = 1; - setMoveRect(0, 224, 0, 127); + setMoveRect(0, 0, 224, 127); } if (_window6Flag == 1) @@ -304,7 +304,123 @@ void AGOSEngine::animateSprites() { } void AGOSEngine::dirtyClips() { - // TODO + int16 x, y, w, h; +restart: + _newDirtyClip = 0; + + VgaSprite *vsp = _vgaSprites; + while (vsp->id != 0) { + if (vsp->windowNum & 0x8000) { + x = vsp->x; + y = vsp->y; + w = 1; + h = 1; + + if (vsp->image != 0) { + VgaPointersEntry *vpe = &_vgaBufferPointers[vsp->zoneNum]; + const byte *ptr = vpe->vgaFile2 + vsp->image * 8; + w = READ_BE_UINT16(ptr + 6) / 8; + h = ptr[5]; + } + + dirtyClipCheck(x, y, w, h); + } + vsp++; + } + + AnimTable *animTable = _screenAnim1; + while (animTable->srcPtr != 0) { + if (animTable->windowNum & 0x8000) { + x = animTable->x + _scrollX; + y = animTable->y; + w = animTable->width * 2; + h = animTable->height; + + dirtyClipCheck(x, y, w, h); + } + animTable++; + } + + if (_newDirtyClip != 0) + goto restart; + +} + +void AGOSEngine::dirtyClipCheck(int16 x, int16 y, int16 w, int16 h) { + int16 width, height, tmp; + + VgaSprite *vsp = _vgaSprites; + for (; vsp->id != 0; vsp++) { + if (vsp->windowNum & 0x8000) + continue; + + if (vsp->image == 0) + continue; + + VgaPointersEntry *vpe = &_vgaBufferPointers[vsp->zoneNum]; + const byte *ptr = vpe->vgaFile2 + vsp->image * 8; + width = READ_BE_UINT16(ptr + 6) / 8; + height = ptr[5]; + + tmp = vsp->x; + if (tmp >= x) { + tmp -= w; + if (tmp >= x) + continue; + } else { + tmp += width; + if (tmp < x) + continue; + } + + tmp = vsp->y; + if (tmp >= y) { + tmp -= h; + if (tmp >= y) + continue; + } else { + tmp += height; + if (tmp < y) + continue; + } + + vsp->windowNum |= 0x8000; + _newDirtyClip = 1; + } + + AnimTable *animTable = _screenAnim1; + for (; animTable->srcPtr != 0; animTable++) { + if (animTable->windowNum & 0x8000) + continue; + + width = animTable->width * 2; + height = animTable->height; + + tmp = animTable->x + _scrollX; + if (tmp >= x) { + tmp -= w; + if (tmp >= x) + continue; + } else { + tmp += width; + if (tmp < x) + continue; + } + + tmp = animTable->y; + if (tmp >= y) { + tmp -= h; + if (tmp >= y) + continue; + } else { + tmp += height; + if (tmp < y) + continue; + } + + animTable->windowNum |= 0x8000; + _newDirtyClip = 1; + } } void AGOSEngine::restoreBackGround() { @@ -326,12 +442,11 @@ void AGOSEngine::restoreBackGround() { animTable--; if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) && - !(animTable->window & 0x8000)) { - //continue; + !(animTable->windowNum & 0x8000)) { + continue; } - animTable->window &= 0x7FFF; - _windowNum = animTable->window; + _windowNum = animTable->windowNum & 0x7FFF; VC10_state state; state.srcPtr = animTable->srcPtr; @@ -346,9 +461,9 @@ void AGOSEngine::restoreBackGround() { _backFlag = 1; drawImage(&state); - //if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2) { + if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2) { animTable->srcPtr = 0; - //} + } } _backFlag = 0; @@ -357,7 +472,7 @@ void AGOSEngine::restoreBackGround() { animTable = animTableTmp = _screenAnim1; while (animTable->srcPtr) { - if (!(animTable->window & 8000)) { + if (!(animTable->windowNum & 0x8000)) { memcpy(animTableTmp, animTable, sizeof(AnimTable)); animTableTmp++; } @@ -402,8 +517,12 @@ void AGOSEngine::saveBackGround(VgaSprite *vsp) { } animTable->height = ptr[5]; - animTable->window = vsp->windowNum; + animTable->windowNum = vsp->windowNum; animTable->id = vsp->id; + animTable->zoneNum = vsp->zoneNum; + + animTable++; + animTable->srcPtr = 0; } void AGOSEngine::displayBoxStars() { @@ -422,10 +541,13 @@ void AGOSEngine::displayBoxStars() { uint curHeight = (getGameType() == GType_SIMON2) ? _boxStarHeight : 134; + for (int i = 0; i < 5; i++) { ha = _hitAreas; count = ARRAYSIZE(_hitAreas); + Graphics::Surface *screen = _system->lockScreen(); + do { if (ha->id != 0 && ha->flags & kBFBoxInUse && !(ha->flags & kBFBoxDead)) { @@ -453,7 +575,7 @@ void AGOSEngine::displayBoxStars() { if (x_ >= 311) continue; - dst = getFrontBuf(); + dst = (byte *)screen->pixels; dst += (((_dxSurfacePitch / 4) * y_) * 4) + x_; @@ -492,6 +614,8 @@ void AGOSEngine::displayBoxStars() { } } while (ha++, --count); + _system->unlockScreen(); + delay(100); setMoveRect(0, 0, 320, curHeight); @@ -509,11 +633,7 @@ void AGOSEngine::scrollScreen() { const byte *src; uint x, y; - if (getGameType() == GType_SIMON2) { - dst = getBackGround(); - } else { - dst = getFrontBuf(); - } + dst = getBackGround(); if (_scrollXMax == 0) { uint screenSize = 8 * _screenWidth; @@ -536,8 +656,7 @@ void AGOSEngine::scrollScreen() { _scrollY += _scrollFlag; vcWriteVar(250, _scrollY); - memcpy(_backBuf, _frontBuf, _screenWidth * _screenHeight); - memcpy(_backGroundBuf, _backBuf, _screenHeight * _scrollWidth); + fillBackFromBackGround(_screenHeight, _scrollWidth); } else { if (_scrollFlag < 0) { memmove(dst + 8, dst, _screenWidth * _scrollHeight - 8); @@ -565,8 +684,7 @@ void AGOSEngine::scrollScreen() { if (getGameType() == GType_SIMON2) { memcpy(_window4BackScn, _backGroundBuf, _scrollHeight * _screenWidth); } else { - memcpy(_backBuf, _frontBuf, _screenWidth * _screenHeight); - memcpy(_backGroundBuf, _backBuf, _scrollHeight * _screenWidth); + fillBackFromBackGround(_scrollHeight, _screenWidth); } setMoveRect(0, 0, 320, _scrollHeight); @@ -575,49 +693,48 @@ void AGOSEngine::scrollScreen() { } _scrollFlag = 0; -} -void AGOSEngine::clearBackFromTop(uint lines) { - memset(_backBuf, 0, lines * _screenWidth); -} + if (getGameType() == GType_SIMON2) { + AnimTable *animTable = _screenAnim1; + while (animTable->srcPtr) { + animTable->srcPtr = 0; + animTable++; + } -void AGOSEngine::clearSurfaces(uint num_lines) { - memset(_backBuf, 0, num_lines * _screenWidth); + VgaSprite *vsp = _vgaSprites; + while (vsp->id) { + vsp->windowNum |= 0x8000; + vsp++; + } + } +} - _system->copyRectToScreen(_backBuf, _screenWidth, 0, 0, _screenWidth, num_lines); +void AGOSEngine::clearSurfaces() { + _system->clearScreen(); - if (_useBackGround) { - memset(_frontBuf, 0, num_lines * _screenWidth); - memset(_backGroundBuf, 0, num_lines * _screenWidth); + if (_backBuf) { + memset(_backBuf, 0, _screenHeight * _screenWidth); } } -void AGOSEngine::fillFrontFromBack(uint x, uint y, uint w, uint h) { - uint offs = x + y * _screenWidth; - byte *s = _backBuf + offs; - byte *d = _frontBuf + offs; - - do { - memcpy(d, s, w); - d += _screenWidth; - s += _screenWidth; - } while (--h); +void AGOSEngine::fillBackFromBackGround(uint16 height, uint16 width) { + memcpy(_backBuf, _backGroundBuf, height * width); } -void AGOSEngine::fillBackFromFront(uint x, uint y, uint w, uint h) { - uint offs = x + y * _screenWidth; - byte *s = _frontBuf + offs; - byte *d = _backBuf + offs; +void AGOSEngine::fillBackFromFront() { + Graphics::Surface *screen = _system->lockScreen(); + memcpy(_backBuf, (byte *)screen->pixels, _screenHeight * _screenWidth); + _system->unlockScreen(); +} - do { - memcpy(d, s, w); - d += _screenWidth; - s += _screenWidth; - } while (--h); +void AGOSEngine::fillBackGroundFromBack() { + memcpy(_backGroundBuf, _backBuf, _screenHeight * _screenWidth); } -void AGOSEngine::fillBackGroundFromBack(uint lines) { - memcpy(_backGroundBuf, _backBuf, lines * _screenWidth); +void AGOSEngine::fillBackGroundFromFront() { + Graphics::Surface *screen = _system->lockScreen(); + memcpy(_backGroundBuf, (byte *)screen->pixels, _screenHeight * _screenWidth); + _system->unlockScreen(); } void AGOSEngine::setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height) { @@ -643,18 +760,18 @@ void AGOSEngine::displayScreen() { } } + Graphics::Surface *screen = _system->lockScreen(); if (getGameType() == GType_PP || getGameType() == GType_FF) { - _system->copyRectToScreen(getBackBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight); - _system->updateScreen(); + memcpy((byte *)screen->pixels, getBackBuf(), _screenWidth * _screenHeight); if (getGameId() != GID_DIMP) - memcpy(getBackBuf(), getFrontBuf(), _screenWidth * _screenHeight); + fillBackFromBackGround(_screenHeight, _screenWidth); } else { if (_window4Flag == 2) { _window4Flag = 0; uint16 srcWidth, width, height; - byte *dst = getFrontBuf(); + byte *dst = (byte *)screen->pixels; const byte *src = _window4BackScn; if (_window3Flag == 1) { @@ -688,18 +805,17 @@ void AGOSEngine::displayScreen() { _window6Flag = 0; byte *src = _window6BackScn; - byte *dst = getFrontBuf() + 16320; + byte *dst = (byte *)screen->pixels + 16320; for (int i = 0; i < 80; i++) { memcpy(dst, src, 48); dst += _screenWidth; src += 48; } } - - _system->copyRectToScreen(getFrontBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight); - _system->updateScreen(); } + _system->unlockScreen(); + if (getGameType() == GType_FF && _scrollFlag) { scrollScreen(); } diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp index 8570859bb8..32329f34d9 100644 --- a/engines/agos/event.cpp +++ b/engines/agos/event.cpp @@ -34,11 +34,13 @@ #include "gui/about.h" +#include "graphics/surface.h" + #include "sound/audiocd.h" namespace AGOS { -void AGOSEngine::addTimeEvent(uint timeout, uint subroutine_id) { +void AGOSEngine::addTimeEvent(uint16 timeout, uint16 subroutine_id) { TimeEvent *te = (TimeEvent *)malloc(sizeof(TimeEvent)), *first, *last = NULL; time_t cur_time; @@ -366,13 +368,17 @@ static const byte _image4[32] = { void AGOSEngine::drawStuff(const byte *src, uint xoffs) { const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 132 : 135; - byte *dst = getFrontBuf() + y * _screenWidth + xoffs; + + Graphics::Surface *screen = _system->lockScreen(); + byte *dst = (byte *)screen->pixels + y * _screenWidth + xoffs; for (uint h = 0; h < 6; h++) { memcpy(dst, src, 4); src += 4; dst += _screenWidth; } + + _system->unlockScreen(); } void AGOSEngine::imageEvent2(VgaTimerEntry * vte, uint dx) { @@ -424,28 +430,27 @@ void AGOSEngine::delay(uint amount) { uint32 start = _system->getMillis(); uint32 cur = start; - uint this_delay, vga_period; + uint this_delay, vgaPeriod; AudioCD.updateCD(); if (_debugger->isAttached()) _debugger->onFrame(); - if (_fastMode) - vga_period = 10; - else if (getGameType() == GType_SIMON2) - vga_period = 45; - else - vga_period = 50; + vgaPeriod = (_fastMode) ? 10 : _vgaPeriod; + if (getGameType() == GType_PP && getGameId() != GID_DIMP) { + if (vgaPeriod == 15 && _variableArray[999] == 0) + vgaPeriod = 30; + } _rnd.getRandomNumber(2); do { - while (!_inCallBack && cur >= _lastVgaTick + vga_period && !_pause) { - _lastVgaTick += vga_period; + while (!_inCallBack && cur >= _lastVgaTick + vgaPeriod && !_pause) { + _lastVgaTick += vgaPeriod; // don't get too many frames behind - if (cur >= _lastVgaTick + vga_period * 2) + if (cur >= _lastVgaTick + vgaPeriod * 2) _lastVgaTick = cur; _inCallBack = true; @@ -456,15 +461,16 @@ void AGOSEngine::delay(uint amount) { while (_eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: - if (event.kbd.keycode >= '0' && event.kbd.keycode <='9' + if (event.kbd.keycode >= Common::KEYCODE_0 && event.kbd.keycode <= Common::KEYCODE_9 && (event.kbd.flags == Common::KBD_ALT || event.kbd.flags == Common::KBD_CTRL)) { - _saveLoadSlot = event.kbd.keycode - '0'; + _saveLoadSlot = event.kbd.keycode - Common::KEYCODE_0; // There is no save slot 0 if (_saveLoadSlot == 0) _saveLoadSlot = 10; + memset(_saveLoadName, 0, sizeof(_saveLoadName)); sprintf(_saveLoadName, "Quick %d", _saveLoadSlot); _saveLoadType = (event.kbd.flags == Common::KBD_ALT) ? 1 : 2; @@ -473,14 +479,17 @@ void AGOSEngine::delay(uint amount) { if (!_mouseHideCount && !_showPreposition) quickLoadOrSave(); } else if (event.kbd.flags == Common::KBD_CTRL) { - if (event.kbd.keycode == 'a') { + if (event.kbd.keycode == Common::KEYCODE_a) { GUI::Dialog *_aboutDialog; _aboutDialog = new GUI::AboutDialog(); _aboutDialog->runModal(); - } else if (event.kbd.keycode == 'f') + } else if (event.kbd.keycode == Common::KEYCODE_f) { _fastMode ^= 1; - else if (event.kbd.keycode == 'd') + } else if (event.kbd.keycode == Common::KEYCODE_d) { _debugger->attach(); + } else if (event.kbd.keycode == Common::KEYCODE_u) { + dumpAllSubroutines(); + } } if (getGameType() == GType_PP) { @@ -491,7 +500,7 @@ void AGOSEngine::delay(uint amount) { } // Make sure backspace works right (this fixes a small issue on OS X) - if (event.kbd.keycode == 8) + if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) _keyPressed = 8; else _keyPressed = (byte)event.kbd.ascii; @@ -510,6 +519,7 @@ void AGOSEngine::delay(uint amount) { _leftButton = 0; _leftButtonCount = 0; + _leftClick = true; break; case Common::EVENT_RBUTTONDOWN: if (getGameType() == GType_FF) @@ -544,32 +554,17 @@ void AGOSEngine::delay(uint amount) { } void AGOSEngine::timer_callback() { - // FIXME: _timer5 is never set - if (_timer5) { - _syncFlag2 = true; - _timer5--; - } else { - if (getGameId() == GID_DIMP) { - _thisTickCount = _system->getMillis(); - if (_thisTickCount < _lastTickCount) - _lastTickCount = 0; - - if ((_thisTickCount - _lastTickCount) <= 35) - return; - - _lastTickCount = _thisTickCount; + if (getGameId() == GID_DIMP) { + _lastTickCount = _system->getMillis(); - timer_proc1(); - dimp_idle(); - } else { - timer_proc1(); - } + timer_proc1(); + dimp_idle(); + } else { + timer_proc1(); } } void AGOSEngine_Feeble::timer_proc1() { - _timer4++; - if (_lockWord & 0x80E9 || _lockWord & 2) return; @@ -598,11 +593,6 @@ void AGOSEngine_Feeble::timer_proc1() { animateSprites(); } - if (_copyPartialMode == 2) { - fillFrontFromBack(0, 0, _screenWidth, _screenHeight); - _copyPartialMode = 0; - } - if (_displayScreen) { if (getGameType() == GType_FF) { if (!getBitFlag(78)) { @@ -621,8 +611,6 @@ void AGOSEngine_Feeble::timer_proc1() { } void AGOSEngine::timer_proc1() { - _timer4++; - if (_lockWord & 0x80E9 || _lockWord & 2) return; @@ -640,13 +628,6 @@ void AGOSEngine::timer_proc1() { processVgaEvents(); } - if (_updateScreen) { - _system->copyRectToScreen(getFrontBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight); - _system->updateScreen(); - - _updateScreen = false; - } - if (_displayScreen) { displayScreen(); _displayScreen = false; diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 6486cc8ca7..2b530fdcd6 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -25,6 +25,10 @@ #include "common/stdafx.h" +#include "common/system.h" + +#include "graphics/surface.h" + #include "agos/agos.h" #include "agos/intern.h" #include "agos/vga.h" @@ -289,6 +293,9 @@ void AGOSEngine_Feeble::scaleClip(int16 h, int16 w, int16 y, int16 x, int16 scro } void AGOSEngine_Feeble::drawImage(VC10_state *state) { + state->surf_addr = getBackBuf(); + state->surf_pitch = _dxSurfacePitch; + if (state->flags & kDFCompressed) { if (state->flags & kDFScaled) { state->surf_addr = getScaleBuf(); @@ -357,8 +364,9 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { scaleClip(_scaleHeight, _scaleWidth, _scaleY, _scaleX, _scaleY + _scrollY); } } else { - if (!drawImage_clip(state)) + if (!drawImage_clip(state)) { return; + } state->surf_addr += state->x + state->y * state->surf_pitch; @@ -373,14 +381,18 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { if (state->flags & kDFMasked) { if (getGameType() == GType_FF && !getBitFlag(81)) { - if (state->x > _feebleRect.right) + if (state->x > _feebleRect.right) { return; - if (state->y > _feebleRect.bottom) + } + if (state->y > _feebleRect.bottom) { return; - if (state->x + state->width < _feebleRect.left) + } + if (state->x + state->width < _feebleRect.left) { return; - if (state->y + state->height < _feebleRect.top) + } + if (state->y + state->height < _feebleRect.top) { return; + } } dstPtr = state->surf_addr; @@ -423,8 +435,9 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { } } } else { - if (!drawImage_clip(state)) + if (!drawImage_clip(state)) { return; + } state->surf_addr += state->x + state->y * state->surf_pitch; @@ -448,7 +461,7 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { dst += _screenWidth; src += state->width; } while (--state->draw_height); - } + } } void AGOSEngine_Simon1::drawMaskedImage(VC10_state *state) { @@ -629,6 +642,8 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { if (!drawImage_clip(state)) return; + Graphics::Surface *screen = _system->lockScreen(); + if (getFeatures() & GF_32COLOR) state->palette = 0xC0; @@ -663,7 +678,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { _window4Flag = 1; } else { - state->surf_addr = getFrontBuf(); + state->surf_addr = (byte *)screen->pixels; state->surf_pitch = _screenWidth; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -697,7 +712,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { state->surf2_addr = getBackGround(); state->surf2_pitch = _screenWidth; - state->surf_addr = getFrontBuf(); + state->surf_addr = (byte *)screen->pixels; state->surf_pitch = _screenWidth; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -717,6 +732,8 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { } else { drawVertImage(state); } + + _system->unlockScreen(); } void AGOSEngine::drawBackGroundImage(VC10_state *state) { @@ -812,6 +829,8 @@ void AGOSEngine::drawImage(VC10_state *state) { if (!drawImage_clip(state)) return; + Graphics::Surface *screen = _system->lockScreen(); + uint16 xoffs, yoffs; if (getGameType() == GType_WW) { if (_windowNum == 4 || (_windowNum >= 10 && _windowNum <= 27)) { @@ -827,7 +846,7 @@ void AGOSEngine::drawImage(VC10_state *state) { _window4Flag = 1; } else { - state->surf_addr = getFrontBuf(); + state->surf_addr = (byte *)screen->pixels; state->surf_pitch = _screenWidth; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -847,7 +866,7 @@ void AGOSEngine::drawImage(VC10_state *state) { _window4Flag = 1; } else { - state->surf_addr = getFrontBuf(); + state->surf_addr = (byte *)screen->pixels; state->surf_pitch = _screenWidth; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -861,7 +880,7 @@ void AGOSEngine::drawImage(VC10_state *state) { xoffs = state->x * 8; yoffs = state->y; } else if (_windowNum == 2 || _windowNum == 3) { - state->surf_addr = getFrontBuf(); + state->surf_addr = (byte *)screen->pixels; state->surf_pitch = _screenWidth; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -894,6 +913,8 @@ void AGOSEngine::drawImage(VC10_state *state) { } else { drawVertImage(state); } + + _system->unlockScreen(); } void AGOSEngine::horizontalScroll(VC10_state *state) { @@ -1008,11 +1029,7 @@ void AGOSEngine::animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, i else vsp->palette = palette; vsp->id = vgaSpriteId; - - if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) - vsp->zoneNum = zoneNum; - else - vsp->zoneNum = zoneNum = vgaSpriteId / 100; + vsp->zoneNum = zoneNum; for (;;) { vpe = &_vgaBufferPointers[zoneNum]; @@ -1255,14 +1272,14 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { _windowNum = updateWindow = mode; _lockWord |= 0x20; - VgaTimerEntry *vte = _vgaTimerList; - while (vte->type != 2) - vte++; - - vte->delay = 2; - if (getGameType() == GType_FF || getGameType() == GType_PP) { vc27_resetSprite(); + } else { + VgaTimerEntry *vte = _vgaTimerList; + while (vte->type != ANIMATE_INT) + vte++; + + vte->delay = 2; } if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) { @@ -1284,8 +1301,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { setImage(vga_res_id); if (getGameType() == GType_FF || getGameType() == GType_PP) { - fillFrontFromBack(0, 0, _screenWidth, _screenHeight); - fillBackGroundFromBack(_screenHeight); + fillBackGroundFromBack(); _syncFlag2 = 1; } else { _copyScnFlag = 2; @@ -1302,6 +1318,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { uint width = _videoWindows[updateWindow * 4 + 2] * 16; uint height = _videoWindows[updateWindow * 4 + 3]; + Graphics::Surface *screen = _system->lockScreen(); byte *dst = getBackGround() + xoffs + yoffs * _screenWidth; byte *src; uint srcWidth; @@ -1315,9 +1332,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { src = _window4BackScn; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3 || updateWindow == 9) { - src = getFrontBuf() + xoffs + yoffs * _screenWidth; + src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; srcWidth = _screenWidth; } else { + _system->unlockScreen(); _lockWord &= ~0x20; return; } @@ -1329,9 +1347,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { src = _window4BackScn + xoffs + yoffs * 320; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 0) { - src = getFrontBuf() + xoffs + yoffs * _screenWidth; + src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; srcWidth = _screenWidth; } else { + _system->unlockScreen(); _lockWord &= ~0x20; return; } @@ -1340,9 +1359,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { src = _window4BackScn; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3 || updateWindow == 9) { - src = getFrontBuf() + xoffs + yoffs * _screenWidth; + src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; srcWidth = _screenWidth; } else { + _system->unlockScreen(); _lockWord &= ~0x20; return; } @@ -1351,9 +1371,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { src = _window4BackScn; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3) { - src = getFrontBuf() + xoffs + yoffs * _screenWidth; + src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; srcWidth = _screenWidth; } else { + _system->unlockScreen(); _lockWord &= ~0x20; return; } @@ -1363,7 +1384,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { src = _window6BackScn; srcWidth = 48; } else if (updateWindow == 2 || updateWindow == 3) { - src = getFrontBuf() + xoffs + yoffs * _screenWidth; + src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; srcWidth = _screenWidth; } else { src = _window4BackScn; @@ -1380,7 +1401,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { } if (getGameType() == GType_ELVIRA1 && updateWindow == 3 && _bottomPalette) { - dst = getFrontBuf() + 133 * _screenWidth; + dst = (byte *)screen->pixels + 133 * _screenWidth; int size = 67 * _screenWidth; while (size--) { @@ -1389,8 +1410,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vga_res_id) { } } - _syncFlag2 = 1; - _timer5 = 0; + _system->unlockScreen(); } _lockWord &= ~0x20; diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp index 9c8938bb97..3edcedaa8e 100644 --- a/engines/agos/icons.cpp +++ b/engines/agos/icons.cpp @@ -25,27 +25,44 @@ #include "common/stdafx.h" +#include "common/system.h" + #include "common/file.h" +#include "graphics/surface.h" + #include "agos/agos.h" namespace AGOS { void AGOSEngine::loadIconFile() { Common::File in; - uint size; + uint32 srcSize; in.open(getFileName(GAME_ICONFILE)); if (in.isOpen() == false) error("Can't open icons file '%s'", getFileName(GAME_ICONFILE)); - size = in.size(); + srcSize = in.size(); - _iconFilePtr = (byte *)malloc(size); - if (_iconFilePtr == NULL) - error("Out of icon memory"); + if (getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) { + byte *srcBuf = (byte *)malloc(srcSize); + in.read(srcBuf, srcSize); + + uint32 dstSize = READ_BE_UINT32(srcBuf + srcSize - 4); + _iconFilePtr = (byte *)malloc(dstSize); + if (_iconFilePtr == NULL) + error("Out of icon memory"); + + decrunchFile(srcBuf, _iconFilePtr, srcSize); + free(srcBuf); + } else { + _iconFilePtr = (byte *)malloc(srcSize); + if (_iconFilePtr == NULL) + error("Out of icon memory"); - in.read(_iconFilePtr, size); + in.read(_iconFilePtr, srcSize); + } in.close(); } @@ -66,15 +83,19 @@ void AGOSEngine::loadIconData() { // Thanks to Stuart Caie for providing the original // C conversion upon which this function is based. static void decompressIconPlanar(byte *dst, byte *src, uint width, uint height, byte base, uint pitch, bool decompress = true) { - byte icon_pln[288]; - byte *i, *o, *srcPtr, x, y; + byte *i, *icon_pln, *o, *srcPtr; + byte x, y; + icon_pln = 0; srcPtr = src; + if (decompress) { + icon_pln = (byte *)calloc(width * height, 1); + // Decode RLE planar icon data i = src; o = icon_pln; - while (o < &icon_pln[288]) { + while (o < &icon_pln[width * height]) { x = *i++; if (x < 128) { do { @@ -96,18 +117,20 @@ static void decompressIconPlanar(byte *dst, byte *src, uint width, uint height, } // Translate planar data to chunky (very slow method) - for (y = 0; y < 24; y++) { - for (x = 0; x < 24; x++) { + for (y = 0; y < height * 2; y++) { + for (x = 0; x < width; x++) { byte pixel = - (srcPtr[(( y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 1 : 0) - | (srcPtr[((24 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 2 : 0) - | (srcPtr[((48 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 4 : 0) - | (srcPtr[((72 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 8 : 0); + (srcPtr[((height * 0 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 1 : 0) + | (srcPtr[((height * 2 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 2 : 0) + | (srcPtr[((height * 4 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 4 : 0) + | (srcPtr[((height * 6 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 8 : 0); if (pixel) dst[x] = pixel | base; } dst += pitch; } + + free(icon_pln); } static void decompressIcon(byte *dst, byte *src, uint width, uint height, byte base, uint pitch) { @@ -174,20 +197,24 @@ void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y) byte *src; _lockWord |= 0x8000; - dst = getFrontBuf(); + + Graphics::Surface *screen = _system->lockScreen(); + dst = (byte *)screen->pixels; dst += 110; dst += x; dst += (y + window->y) * _dxSurfacePitch; src = _iconFilePtr; - src += READ_LE_UINT16(&((uint16 *)src)[icon * 2 + 0]); + src += READ_LE_UINT16(src + icon * 4 + 0); decompressIcon(dst, src, 20, 10, 224, _dxSurfacePitch); src = _iconFilePtr; - src += READ_LE_UINT16(&((uint16 *)src)[icon * 2 + 1]); + src += READ_LE_UINT16(src + icon * 4 + 2); decompressIcon(dst, src, 20, 10, 208, _dxSurfacePitch); + _system->unlockScreen(); + _lockWord &= ~0x8000; } @@ -196,22 +223,26 @@ void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) byte *src; _lockWord |= 0x8000; - dst = getFrontBuf(); + + Graphics::Surface *screen = _system->lockScreen(); + dst = (byte *)screen->pixels; dst += (x + window->x) * 8; dst += (y * 25 + window->y) * _dxSurfacePitch; if (getPlatform() == Common::kPlatformAmiga) { src = _iconFilePtr; - src += READ_BE_UINT32(&((uint32 *)src)[icon]); + src += READ_BE_UINT32(src + icon * 4); uint8 color = (getFeatures() & GF_32COLOR) ? 16 : 240; - decompressIconPlanar(dst, src, 24, 24, color, _dxSurfacePitch); + decompressIconPlanar(dst, src, 24, 12, color, _dxSurfacePitch); } else { src = _iconFilePtr; - src += READ_LE_UINT16(&((uint16 *)src)[icon]); + src += READ_LE_UINT16(src + icon * 2); decompressIcon(dst, src, 24, 12, 224, _dxSurfacePitch); } + _system->unlockScreen(); + _lockWord &= ~0x8000; } @@ -220,21 +251,26 @@ void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint byte *src; _lockWord |= 0x8000; - dst = getFrontBuf(); + + Graphics::Surface *screen = _system->lockScreen(); + dst = (byte *)screen->pixels; dst += (x + window->x) * 8; dst += (y * 20 + window->y) * _dxSurfacePitch; uint8 color = dst[0] & 0xF0; if (getPlatform() == Common::kPlatformAmiga) { - // TODO - return; + src = _iconFilePtr; + src += READ_BE_UINT32(src + icon * 4); + decompressIconPlanar(dst, src, 24, 10, color, _dxSurfacePitch); } else { src = _iconFilePtr; - src += READ_LE_UINT16(&((uint16 *)src)[icon]); + src += READ_LE_UINT16(src + icon * 2); decompressIcon(dst, src, 24, 10, color, _dxSurfacePitch); } + _system->unlockScreen(); + _lockWord &= ~0x8000; } @@ -243,7 +279,9 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y byte *src; _lockWord |= 0x8000; - dst = getFrontBuf(); + + Graphics::Surface *screen = _system->lockScreen(); + dst = (byte *)screen->pixels; dst += (x + window->x) * 8; dst += (y * 8 + window->y) * _dxSurfacePitch; @@ -251,14 +289,16 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y uint color = dst[0] & 0xF0; if (getFeatures() & GF_PLANAR) { src = _iconFilePtr; - src += READ_BE_UINT32(&((uint32 *)src)[icon]); - decompressIconPlanar(dst, src, 24, 24, color, _dxSurfacePitch); + src += READ_BE_UINT32(src + icon * 4); + decompressIconPlanar(dst, src, 24, 12, color, _dxSurfacePitch); } else { src = _iconFilePtr; - src += READ_LE_UINT16(&((uint16 *)src)[icon]); + src += READ_LE_UINT16(src + icon * 2); decompressIcon(dst, src, 24, 12, color, _dxSurfacePitch); } + _system->unlockScreen(); + _lockWord &= ~0x8000; } @@ -267,21 +307,25 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) { byte *src; _lockWord |= 0x8000; - dst = getFrontBuf(); + + Graphics::Surface *screen = _system->lockScreen(); + dst = (byte *)screen->pixels; dst += (x + window->x) * 8; dst += (y * 8 + window->y) * _dxSurfacePitch; if (getFeatures() & GF_PLANAR) { src = _iconFilePtr; - src += READ_BE_UINT16(&((uint16 *)src)[icon]); - decompressIconPlanar(dst, src, 24, 24, 16, _dxSurfacePitch); + src += READ_BE_UINT16(src + icon * 2); + decompressIconPlanar(dst, src, 24, 12, 16, _dxSurfacePitch); } else { src = _iconFilePtr; src += icon * 288; - decompressIconPlanar(dst, src, 24, 24, 16, _dxSurfacePitch, false); + decompressIconPlanar(dst, src, 24, 12, 16, _dxSurfacePitch, false); } + _system->unlockScreen(); + _lockWord &= ~0x8000; } @@ -384,7 +428,7 @@ l1:; itemRef = derefItem(itemRef->next); } /* Plot arrows and add their boxes */ - addArrows(window); + addArrows(window, num); window->iconPtr->upArrow = _scrollUpHitArea; window->iconPtr->downArrow = _scrollDownHitArea; } @@ -486,7 +530,7 @@ void AGOSEngine::drawIconArray(uint num, Item *itemRef, int line, int classMask) if (showArrows != 0 || window->iconPtr->line != 0) { /* Plot arrows and add their boxes */ - addArrows(window); + addArrows(window, num); window->iconPtr->upArrow = _scrollUpHitArea; window->iconPtr->downArrow = _scrollDownHitArea; } @@ -594,7 +638,7 @@ uint AGOSEngine::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, return ha - _hitAreas; } -void AGOSEngine_Feeble::addArrows(WindowBlock *window) { +void AGOSEngine_Feeble::addArrows(WindowBlock *window, uint8 num) { HitArea *ha; ha = findEmptyHitArea(); @@ -624,7 +668,7 @@ void AGOSEngine_Feeble::addArrows(WindowBlock *window) { ha->verb = 1; } -void AGOSEngine_Simon2::addArrows(WindowBlock *window) { +void AGOSEngine_Simon2::addArrows(WindowBlock *window, uint8 num) { HitArea *ha; ha = findEmptyHitArea(); @@ -654,7 +698,7 @@ void AGOSEngine_Simon2::addArrows(WindowBlock *window) { ha->verb = 1; } -void AGOSEngine_Simon1::addArrows(WindowBlock *window) { +void AGOSEngine_Simon1::addArrows(WindowBlock *window, uint8 num) { HitArea *ha; ha = findEmptyHitArea(); @@ -683,16 +727,24 @@ void AGOSEngine_Simon1::addArrows(WindowBlock *window) { ha->window = window; ha->verb = 1; - if (getFeatures() & GF_32COLOR) { - // TODO: Manually draws arrows - } else { - stopAnimate(128); - uint8 palette = (getPlatform() == Common::kPlatformAmiga) ? 15: 14; - animate(0, 1, 128, 0, 0, palette); - } + _lockWord |= 0x8; + + VgaPointersEntry *vpe = &_vgaBufferPointers[1]; + byte *curVgaFile2Orig = _curVgaFile2; + uint16 windowNumOrig = _windowNum; + uint8 palette = (getPlatform() == Common::kPlatformAmiga) ? 15 : 14; + + _windowNum = 0; + _curVgaFile2 = vpe->vgaFile2; + drawImage_init(1, palette, 38, 150, 4); + + _curVgaFile2 = curVgaFile2Orig; + _windowNum = windowNumOrig; + + _lockWord &= ~0x8; } -void AGOSEngine_Waxworks::addArrows(WindowBlock *window) { +void AGOSEngine_Waxworks::addArrows(WindowBlock *window, uint8 num) { HitArea *ha; ha = findEmptyHitArea(); @@ -724,7 +776,7 @@ void AGOSEngine_Waxworks::addArrows(WindowBlock *window) { setWindowImageEx(6, 103); } -void AGOSEngine_Elvira2::addArrows(WindowBlock *window) { +void AGOSEngine_Elvira2::addArrows(WindowBlock *window, uint8 num) { HitArea *ha; ha = findEmptyHitArea(); @@ -756,8 +808,17 @@ void AGOSEngine_Elvira2::addArrows(WindowBlock *window) { setWindowImageEx(6, 106); } -void AGOSEngine::addArrows(WindowBlock *window) { +void AGOSEngine::addArrows(WindowBlock *window, uint8 num) { HitArea *ha; + uint16 x, y; + + x = 30; + y = 151; + if (num != 2) { + y = window->height * 4 + window->y - 19; + x = window->width + window->x; + } + drawArrow(x, y, 16); ha = findEmptyHitArea(); _scrollUpHitArea = ha - _hitAreas; @@ -772,6 +833,14 @@ void AGOSEngine::addArrows(WindowBlock *window) { ha->window = window; ha->verb = 1; + x = 30; + y = 170; + if (num != 2) { + y = window->height * 4; + x = window->width + window->x; + } + drawArrow(x, y, -16); + ha = findEmptyHitArea(); _scrollDownHitArea = ha - _hitAreas; @@ -786,21 +855,89 @@ void AGOSEngine::addArrows(WindowBlock *window) { ha->verb = 1; } +static const byte _arrowImage[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, + 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, + 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, + 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x03, + 0x04, 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x03, 0x04, + 0x0f, 0x04, 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, + 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x0d, 0x0d, 0x03, + 0x04, 0x03, 0x0d, 0x0d, 0x0d, 0x0a, 0x0b, 0x0a, + 0x00, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x0d, + 0x03, 0x0d, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, + 0x00, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0d, + 0x0d, 0x0d, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x00, 0x0a, 0x0a, 0x0a, 0x0e, 0x0b, 0x0b, 0x0c, + 0x0e, 0x0c, 0x0b, 0x0b, 0x0e, 0x0a, 0x0a, 0x0a, + 0x00, 0x00, 0x02, 0x02, 0x0a, 0x0b, 0x0a, 0x0d, + 0x0d, 0x0d, 0x0a, 0x0b, 0x0a, 0x02, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x0a, 0x0b, 0x0b, 0x0c, + 0x0e, 0x0c, 0x0b, 0x0b, 0x0a, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, + 0x0d, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0b, 0x0c, + 0x0e, 0x0c, 0x0b, 0x0b, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x0a, 0x0a, + 0x0e, 0x0a, 0x0a, 0x0e, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, +}; + +void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) { + const byte *src; + uint8 w, h; + + if (dir < 0) { + src = _arrowImage + 288; + } else { + src = _arrowImage; + } + + Graphics::Surface *screen = _system->lockScreen(); + byte *dst = (byte *)screen->pixels + y * _screenWidth + x * 8; + + for (h = 0; h < 19; h++) { + for (w = 0; w < 16; w++) { + dst[w] = src[w] + 16; + } + + src += dir; + dst+= _screenWidth; + } + + _system->unlockScreen(); +} + void AGOSEngine::removeArrows(WindowBlock *window, uint num) { if (getGameType() == GType_SIMON1) { - if (getFeatures() & GF_32COLOR) { - // TODO: Manually removes arrows - } else { - stopAnimate(129); - uint8 palette = (getPlatform() == Common::kPlatformAmiga) ? 15: 14; - animate(0, 1, 129, 0, 0, palette); - } + restoreBlock(200, 320, 146, 304); } else if (getGameType() == GType_WW) { setBitFlag(22, false); setWindowImageEx(6, 103); } else if (getGameType() == GType_ELVIRA2) { setBitFlag(21, false); setWindowImageEx(6, 106); + } else if (getGameType() == GType_ELVIRA1) { + if (num != 2) { + uint y = window->height * 4 + window->y - 19; + uint x = window->width + window->x; + restoreBlock(y + 38, x + 16, y, x); + } else { + colorBlock(window, 240, 151, 16, 38); + } } } diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp index 3f2efc86b4..ef0791dc10 100644 --- a/engines/agos/input.cpp +++ b/engines/agos/input.cpp @@ -25,6 +25,7 @@ #include "common/stdafx.h" +#include "common/config-manager.h" #include "common/file.h" #include "agos/intern.h" @@ -273,28 +274,28 @@ void AGOSEngine::waitForInput() { _verbHitArea = 236; if (ha->id == 98) { - animate(2, 0, 110, 0, 0, 0); + animate(2, 1, 110, 0, 0, 0); waitForSync(34); } else if (ha->id == 108) { - animate(2, 0, 106, 0, 0, 0); + animate(2, 1, 106, 0, 0, 0); waitForSync(34); } else if (ha->id == 109) { - animate(2, 0, 107, 0, 0, 0); + animate(2, 1, 107, 0, 0, 0); waitForSync(34); } else if (ha->id == 115) { - animate(2, 0, 109, 0, 0, 0); + animate(2, 1, 109, 0, 0, 0); waitForSync(34); } else if (ha->id == 116) { - animate(2, 0, 113, 0, 0, 0); + animate(2, 1, 113, 0, 0, 0); waitForSync(34); } else if (ha->id == 117) { - animate(2, 0, 112, 0, 0, 0); + animate(2, 1, 112, 0, 0, 0); waitForSync(34); } else if (ha->id == 118) { - animate(2, 0, 108, 0, 0, 0); + animate(2, 1, 108, 0, 0, 0); waitForSync(34); } else if (ha->id == 119) { - animate(2, 0, 111, 0, 0, 0); + animate(2, 1, 111, 0, 0, 0); waitForSync(34); } } @@ -542,6 +543,14 @@ bool AGOSEngine::processSpecialKeys() { if (getGameType() == GType_FF) setBitFlag(73, !getBitFlag(73)); break; + case 37: // F12 + if (getGameType() == GType_PP && getGameId() != GID_DIMP) { + if (!getBitFlag(110)) { + setBitFlag(107, !getBitFlag(107)); + _vgaPeriod = (getBitFlag(107) != 0) ? 15 : 30; + } + } + break; case 'p': pause(); break; @@ -558,21 +567,30 @@ bool AGOSEngine::processSpecialKeys() { _speech ^= 1; } case '+': - _midi.setVolume(_midi.getVolume() + 16); + if (_midiEnabled) { + _midi.setVolume(_midi.getVolume() + 16); + } _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 16); break; case '-': - _midi.setVolume(_midi.getVolume() - 16); + if (_midiEnabled) { + _midi.setVolume(_midi.getVolume() - 16); + } _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) - 16); break; case 'm': - _midi.pause(_musicPaused ^= 1); + _musicPaused ^= 1; + if (_midiEnabled) { + _midi.pause(_musicPaused); + } + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (_musicPaused) ? 0 : ConfMan.getInt("music_volume")); break; case 's': - if (getGameId() == GID_SIMON1DOS) + if (getGameId() == GID_SIMON1DOS) { _midi._enable_sfx ^= 1; - else + } else { _sound->effectsPause(_effectsPaused ^= 1); + } break; case 'b': _sound->ambientPause(_ambientPaused ^= 1); diff --git a/engines/agos/intern.h b/engines/agos/intern.h index f39ca7d3da..a863dc7c0f 100644 --- a/engines/agos/intern.h +++ b/engines/agos/intern.h @@ -131,11 +131,11 @@ struct IconBlock { struct WindowBlock { byte mode; byte flags; - uint16 x, y; - uint16 width, height; - uint16 textColumn, textRow; + int16 x, y; + int16 width, height; + int16 textColumn, textRow; + int16 scrollY; uint16 textColumnOffset, textLength, textMaxLength; - uint16 scrollY; uint8 fill_color, text_color; IconBlock *iconPtr; WindowBlock() { memset(this, 0, sizeof(*this)); } diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp index 165af6f797..a911bee5a5 100644 --- a/engines/agos/items.cpp +++ b/engines/agos/items.cpp @@ -391,10 +391,8 @@ int AGOSEngine::wordMatch(Item *item, int16 a, int16 n) { } Item *AGOSEngine::derefItem(uint item) { - if (item >= _itemArraySize) { - debug(1, "derefItem: invalid item %d", item); - return 0; - } + if (item >= _itemArraySize) + error("derefItem: invalid item %d", item); return _itemArrayPtr[item]; } diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp index 802752fad9..6dd1a356d8 100644 --- a/engines/agos/menus.cpp +++ b/engines/agos/menus.cpp @@ -26,6 +26,9 @@ #include "common/stdafx.h" #include "common/file.h" +#include "common/system.h" + +#include "graphics/surface.h" #include "agos/agos.h" #include "agos/intern.h" @@ -145,7 +148,8 @@ void AGOSEngine::unlightMenuStrip() { mouseOff(); - src = getFrontBuf() + 2832; + Graphics::Surface *screen = _system->lockScreen(); + src = (byte *)screen->pixels + 2832; w = 48; h = 82; @@ -160,6 +164,8 @@ void AGOSEngine::unlightMenuStrip() { for (i = 120; i != 130; i++) disableBox(i); + _system->unlockScreen(); + mouseOn(); } @@ -170,7 +176,8 @@ void AGOSEngine::lightMenuBox(uint hitarea) { mouseOff(); - src = getFrontBuf() + ha->y * _dxSurfacePitch + ha->x; + Graphics::Surface *screen = _system->lockScreen(); + src = (byte *)screen->pixels + ha->y * _dxSurfacePitch + ha->x; w = ha->width; h = ha->height; @@ -182,6 +189,8 @@ void AGOSEngine::lightMenuBox(uint hitarea) { src += _dxSurfacePitch; } while (--h); + _system->unlockScreen(); + mouseOn(); } diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp index c38ee8fa6d..787596a966 100644 --- a/engines/agos/oracle.cpp +++ b/engines/agos/oracle.cpp @@ -26,6 +26,9 @@ #include "common/stdafx.h" #include "common/savefile.h" +#include "common/system.h" + +#include "graphics/surface.h" #include "agos/agos.h" #include "agos/intern.h" @@ -247,8 +250,8 @@ void AGOSEngine_Feeble::scrollOracleUp() { byte *src, *dst; uint16 w, h; - dst = getFrontBuf() + 103 * _screenWidth + 136; - src = getFrontBuf() + 106 * _screenWidth + 136; + dst = getBackGround() + 103 * _screenWidth + 136; + src = getBackGround() + 106 * _screenWidth + 136; for (h = 0; h < 21; h++) { for (w = 0; w < 360; w++) { @@ -276,8 +279,8 @@ void AGOSEngine_Feeble::scrollOracleDown() { byte *src, *dst; uint16 w, h; - src = getFrontBuf() + 203 * _screenWidth + 136; - dst = getFrontBuf() + 206 * _screenWidth + 136; + src = getBackGround() + 203 * _screenWidth + 136; + dst = getBackGround() + 206 * _screenWidth + 136; for (h = 0; h < 77; h++) { memcpy(dst, src, 360); @@ -507,7 +510,7 @@ void AGOSEngine_Feeble::windowBackSpace(WindowBlock *window) { x = window->x + window->textColumn; y = window->y + window->textRow; - dst = getFrontBuf() + _dxSurfacePitch * y + x; + dst = getBackGround() + _dxSurfacePitch * y + x; for (h = 0; h < 13; h++) { for (w = 0; w < 8; w++) { diff --git a/engines/agos/res.cpp b/engines/agos/res.cpp index f5936b7d85..394c4956ae 100644 --- a/engines/agos/res.cpp +++ b/engines/agos/res.cpp @@ -351,104 +351,130 @@ void AGOSEngine::readItemFromGamePc(Common::SeekableReadStream *in, Item *item) void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) { if (type == 1) { - if (getGameType() == GType_ELVIRA1) { - SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, 1, sizeof(SubRoom)); - subRoom->roomShort = in->readUint32BE(); - subRoom->roomLong = in->readUint32BE(); - subRoom->flags = in->readUint16BE(); - } else { - uint fr1 = in->readUint16BE(); - uint fr2 = in->readUint16BE(); - uint i, size; - uint j, k; - SubRoom *subRoom; - - size = SubRoom_SIZE; - for (i = 0, j = fr2; i != 6; i++, j >>= 2) - if (j & 3) - size += sizeof(subRoom->roomExit[0]); - - subRoom = (SubRoom *)allocateChildBlock(item, 1, size); - subRoom->subroutine_id = fr1; - subRoom->roomExitStates = fr2; - - for (i = k = 0, j = fr2; i != 6; i++, j >>= 2) - if (j & 3) - subRoom->roomExit[k++] = (uint16)fileReadItemID(in); - } + SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, 1, sizeof(SubRoom)); + subRoom->roomShort = in->readUint32BE(); + subRoom->roomLong = in->readUint32BE(); + subRoom->flags = in->readUint16BE(); } else if (type == 2) { - if (getGameType() == GType_ELVIRA1) { - SubObject *subObject = (SubObject *)allocateChildBlock(item, 2, sizeof(SubObject)); - in->readUint32BE(); - in->readUint32BE(); - in->readUint32BE(); - subObject->objectName = in->readUint32BE(); - subObject->objectSize = in->readUint16BE(); - subObject->objectWeight = in->readUint16BE(); - subObject->objectFlags = in->readUint16BE(); - } else { - uint32 fr = in->readUint32BE(); - uint i, k, size; - SubObject *subObject; + SubObject *subObject = (SubObject *)allocateChildBlock(item, 2, sizeof(SubObject)); + in->readUint32BE(); + in->readUint32BE(); + in->readUint32BE(); + subObject->objectName = in->readUint32BE(); + subObject->objectSize = in->readUint16BE(); + subObject->objectWeight = in->readUint16BE(); + subObject->objectFlags = in->readUint16BE(); + } else if (type == 4) { + SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, 4, sizeof(SubGenExit)); + genExit->dest[0] = (uint16)fileReadItemID(in); + genExit->dest[1] = (uint16)fileReadItemID(in); + genExit->dest[2] = (uint16)fileReadItemID(in); + genExit->dest[3] = (uint16)fileReadItemID(in); + genExit->dest[4] = (uint16)fileReadItemID(in); + genExit->dest[5] = (uint16)fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + } else if (type == 7) { + SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer)); + container->volume = in->readUint16BE(); + container->flags = in->readUint16BE(); + } else if (type == 8) { + SubChain *chain = (SubChain *)allocateChildBlock(item, 8, sizeof(SubChain)); + chain->chChained = (uint16)fileReadItemID(in); + } else if (type == 9) { + setUserFlag(item, 0, in->readUint16BE()); + setUserFlag(item, 1, in->readUint16BE()); + setUserFlag(item, 2, in->readUint16BE()); + setUserFlag(item, 3, in->readUint16BE()); + setUserFlag(item, 4, in->readUint16BE()); + setUserFlag(item, 5, in->readUint16BE()); + setUserFlag(item, 6, in->readUint16BE()); + setUserFlag(item, 7, in->readUint16BE()); + SubUserFlag *subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + subUserFlag->userItems[0] = (uint16)fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + fileReadItemID(in); + } else if (type == 255) { + SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit)); + inherit->inMaster = (uint16)fileReadItemID(in); + } else { + error("readItemChildren: invalid type %d", type); + } +} - size = SubObject_SIZE; - for (i = 0; i != 16; i++) - if (fr & (1 << i)) - size += sizeof(subObject->objectFlagValue[0]); +void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) { + if (type == 1) { + uint fr1 = in->readUint16BE(); + uint fr2 = in->readUint16BE(); + uint i, size; + uint j, k; + SubRoom *subRoom; + + size = SubRoom_SIZE; + for (i = 0, j = fr2; i != 6; i++, j >>= 2) + if (j & 3) + size += sizeof(subRoom->roomExit[0]); + + subRoom = (SubRoom *)allocateChildBlock(item, 1, size); + subRoom->subroutine_id = fr1; + subRoom->roomExitStates = fr2; + + for (i = k = 0, j = fr2; i != 6; i++, j >>= 2) + if (j & 3) + subRoom->roomExit[k++] = (uint16)fileReadItemID(in); + } else if (type == 2) { + uint32 fr = in->readUint32BE(); + uint i, k, size; + SubObject *subObject; - subObject = (SubObject *)allocateChildBlock(item, 2, size); - subObject->objectFlags = fr; + size = SubObject_SIZE; + for (i = 0; i != 16; i++) + if (fr & (1 << i)) + size += sizeof(subObject->objectFlagValue[0]); - k = 0; - if (fr & 1) { - subObject->objectFlagValue[k++] = (uint16)in->readUint32BE(); - } - for (i = 1; i != 16; i++) - if (fr & (1 << i)) - subObject->objectFlagValue[k++] = in->readUint16BE(); + subObject = (SubObject *)allocateChildBlock(item, 2, size); + subObject->objectFlags = fr; - if (getGameType() != GType_ELVIRA2) - subObject->objectName = (uint16)in->readUint32BE(); + k = 0; + if (fr & 1) { + subObject->objectFlagValue[k++] = (uint16)in->readUint32BE(); } + for (i = 1; i != 16; i++) + if (fr & (1 << i)) + subObject->objectFlagValue[k++] = in->readUint16BE(); + + if (getGameType() != GType_ELVIRA2) + subObject->objectName = (uint16)in->readUint32BE(); } else if (type == 4) { - if (getGameType() == GType_ELVIRA2) { - uint i, j, k, size; - uint id, x, y, z; - SubSuperRoom *subSuperRoom; - - id = in->readUint16BE(); - x = in->readUint16BE(); - y = in->readUint16BE(); - z = in->readUint16BE(); - - j = x * y * z; - size = SubSuperRoom_SIZE; - for (i = 0; i != j; i++) - size += sizeof(subSuperRoom->roomExitStates[0]); - - subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, 4, size); - subSuperRoom->subroutine_id = id; - subSuperRoom->roomX = x; - subSuperRoom->roomY = y; - subSuperRoom->roomZ = z; - - for (i = k = 0; i != j; i++) - subSuperRoom->roomExitStates[k++] = in->readUint16BE(); - } else if (getGameType() == GType_ELVIRA1) { - SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, 4, sizeof(SubGenExit)); - genExit->dest[0] = (uint16)fileReadItemID(in); - genExit->dest[1] = (uint16)fileReadItemID(in); - genExit->dest[2] = (uint16)fileReadItemID(in); - genExit->dest[3] = (uint16)fileReadItemID(in); - genExit->dest[4] = (uint16)fileReadItemID(in); - genExit->dest[5] = (uint16)fileReadItemID(in); - fileReadItemID(in); - fileReadItemID(in); - fileReadItemID(in); - fileReadItemID(in); - fileReadItemID(in); - fileReadItemID(in); - } + assert(getGameType() == GType_ELVIRA2); + + uint i, j, k, size; + uint id, x, y, z; + SubSuperRoom *subSuperRoom; + + id = in->readUint16BE(); + x = in->readUint16BE(); + y = in->readUint16BE(); + z = in->readUint16BE(); + + j = x * y * z; + size = SubSuperRoom_SIZE; + for (i = 0; i != j; i++) + size += sizeof(subSuperRoom->roomExitStates[0]); + + subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, 4, size); + subSuperRoom->subroutine_id = id; + subSuperRoom->roomX = x; + subSuperRoom->roomY = y; + subSuperRoom->roomZ = z; + + for (i = k = 0; i != j; i++) + subSuperRoom->roomExitStates[k++] = in->readUint16BE(); } else if (type == 7) { SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer)); container->volume = in->readUint16BE(); @@ -461,17 +487,6 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui setUserFlag(item, 1, in->readUint16BE()); setUserFlag(item, 2, in->readUint16BE()); setUserFlag(item, 3, in->readUint16BE()); - if (getGameType() == GType_ELVIRA1) { - setUserFlag(item, 4, in->readUint16BE()); - setUserFlag(item, 5, in->readUint16BE()); - setUserFlag(item, 6, in->readUint16BE()); - setUserFlag(item, 7, in->readUint16BE()); - SubUserFlag *subUserFlag = (SubUserFlag *) findChildOfType(item, 9); - subUserFlag->userItems[0] = (uint16)fileReadItemID(in); - fileReadItemID(in); - fileReadItemID(in); - fileReadItemID(in); - } } else if (type == 255) { SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit)); inherit->inMaster = (uint16)fileReadItemID(in); @@ -629,7 +644,7 @@ bool AGOSEngine::decrunchFile(byte *src, byte *dst, uint32 size) { #undef SD_TYPE_LITERAL #undef SD_TYPE_MATCH -void AGOSEngine::loadVGABeardFile(uint id) { +void AGOSEngine::loadVGABeardFile(uint16 id) { uint32 offs, size; if (getFeatures() & GF_OLD_BUNDLE) { @@ -673,7 +688,7 @@ void AGOSEngine::loadVGABeardFile(uint id) { } } -void AGOSEngine::loadVGAVideoFile(uint id, uint type) { +void AGOSEngine::loadVGAVideoFile(uint16 id, uint8 type) { File in; char filename[15]; byte *dst; diff --git a/engines/agos/res_snd.cpp b/engines/agos/res_snd.cpp index cc5ba2a793..779ed67e58 100644 --- a/engines/agos/res_snd.cpp +++ b/engines/agos/res_snd.cpp @@ -41,59 +41,59 @@ using Common::File; namespace AGOS { -void AGOSEngine::playSpeech(uint speech_id, uint vgaSpriteId) { - if (getGameType() == GType_SIMON1) { - if (speech_id == 9999) { - if (_subtitles) - return; - if (!getBitFlag(14) && !getBitFlag(28)) { - setBitFlag(14, true); - _variableArray[100] = 15; - animate(4, 1, 130, 0, 0, 0); - waitForSync(130); - } - _skipVgaWait = true; - } else { - if (_subtitles && _scriptVar2) { - animate(4, 2, 204, 0, 0, 0); - waitForSync(204); - stopAnimate(204); - } - if (vgaSpriteId < 100) - stopAnimate(vgaSpriteId + 201); +void AGOSEngine_Simon1::playSpeech(uint16 speech_id, uint16 vgaSpriteId) { + if (speech_id == 9999) { + if (_subtitles) + return; + if (!getBitFlag(14) && !getBitFlag(28)) { + setBitFlag(14, true); + _variableArray[100] = 15; + animate(4, 1, 130, 0, 0, 0); + waitForSync(130); + } + _skipVgaWait = true; + } else { + if (_subtitles && _scriptVar2) { + animate(4, 2, 204, 0, 0, 0); + waitForSync(204); + stopAnimate(204); + } + if (vgaSpriteId < 100) + stopAnimate(201 + vgaSpriteId); - loadVoice(speech_id); + loadVoice(speech_id); - if (vgaSpriteId < 100) - animate(4, 2, vgaSpriteId + 201, 0, 0, 0); + if (vgaSpriteId < 100) + animate(4, 2, 201 + vgaSpriteId, 0, 0, 0); + } +} + +void AGOSEngine_Simon2::playSpeech(uint16 speech_id, uint16 vgaSpriteId) { + if (speech_id == 0xFFFF) { + if (_subtitles) + return; + if (!getBitFlag(14) && !getBitFlag(28)) { + setBitFlag(14, true); + _variableArray[100] = 5; + animate(4, 1, 30, 0, 0, 0); + waitForSync(130); } + _skipVgaWait = true; } else { - if (speech_id == 0xFFFF) { - if (_subtitles) - return; - if (!getBitFlag(14) && !getBitFlag(28)) { - setBitFlag(14, true); - _variableArray[100] = 5; - animate(4, 1, 30, 0, 0, 0); - waitForSync(130); - } - _skipVgaWait = true; - } else { - if (getGameType() == GType_SIMON2 && _subtitles && _language != Common::HB_ISR) { - loadVoice(speech_id); - return; - } - - if (_subtitles && _scriptVar2) { - animate(4, 2, 5, 0, 0, 0); - waitForSync(205); - stopAnimateSimon2(2,5); - } - - stopAnimateSimon2(2, vgaSpriteId + 2); + if (getGameType() == GType_SIMON2 && _subtitles && _language != Common::HB_ISR) { loadVoice(speech_id); - animate(4, 2, vgaSpriteId + 2, 0, 0, 0); + return; + } + + if (_subtitles && _scriptVar2) { + animate(4, 2, 5, 0, 0, 0); + waitForSync(205); + stopAnimateSimon2(2,5); } + + stopAnimateSimon2(2, vgaSpriteId + 2); + loadVoice(speech_id); + animate(4, 2, vgaSpriteId + 2, 0, 0, 0); } } @@ -120,9 +120,26 @@ void AGOSEngine::skipSpeech() { } } -void AGOSEngine::loadModule(uint music) { - _mixer->stopHandle(_modHandle); +void AGOSEngine::loadMusic(uint16 music) { + char buf[4]; + + stopMusic(); + + _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET); + _gameFile->read(buf, 4); + if (!memcmp(buf, "FORM", 4)) { + _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET); + _midi.loadXMIDI(_gameFile); + } else { + _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET); + _midi.loadMultipleSMF(_gameFile); + } + _lastMusicPlayed = music; + _nextMusicToPlay = -1; +} + +void AGOSEngine::playModule(uint16 music) { char filename[15]; File f; @@ -135,7 +152,7 @@ void AGOSEngine::loadModule(uint music) { f.open(filename); if (f.isOpen() == false) { - error("loadModule: Can't load module from '%s'", filename); + error("playModule: Can't load module from '%s'", filename); } Audio::AudioStream *audioStream; @@ -145,7 +162,7 @@ void AGOSEngine::loadModule(uint music) { uint srcSize = f.size(); byte *srcBuf = (byte *)malloc(srcSize); if (f.read(srcBuf, srcSize) != srcSize) - error("loadModule: Read failed"); + error("playModule: Read failed"); uint dstSize = READ_BE_UINT32(srcBuf + srcSize - 4); byte *dstBuf = (byte *)malloc(dstSize); @@ -162,93 +179,93 @@ void AGOSEngine::loadModule(uint music) { _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_modHandle, audioStream); } -void AGOSEngine::loadMusic(uint music) { - char buf[4]; +void AGOSEngine_Simon1::playMusic(uint16 music, uint16 track) { + stopMusic(); - if (getGameType() == GType_SIMON2) { - _midi.stop(); - _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET); + // Support for compressed music from the ScummVM Music Enhancement Project + AudioCD.stop(); + AudioCD.play(music + 1, -1, 0, 0); + if (AudioCD.isPlaying()) + return; + + if (getGameId() == GID_SIMON1ACORN) { + // TODO: Add support for Desktop Tracker format + } else if (getPlatform() == Common::kPlatformAmiga) { + playModule(music); + } else if (getFeatures() & GF_TALKIE) { + char buf[4]; + + // WORKAROUND: For a script bug in the CD versions + // We skip this music resource, as it was replaced by + // a sound effect, and the script was never updated. + if (music == 35) + return; + + _midi.setLoop(true); // Must do this BEFORE loading music. (GMF may have its own override.) + + _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET); _gameFile->read(buf, 4); - if (!memcmp(buf, "FORM", 4)) { - _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET); - _midi.loadXMIDI(_gameFile); + if (!memcmp(buf, "GMF\x1", 4)) { + _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET); + _midi.loadSMF(_gameFile, music); } else { - _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music - 1], SEEK_SET); + _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET); _midi.loadMultipleSMF(_gameFile); } - _lastMusicPlayed = music; - _nextMusicToPlay = -1; - } else if (getGameType() == GType_SIMON1) { - _midi.stop(); + _midi.startTrack(0); + _midi.startTrack(track); + } else { + char filename[15]; + File f; + sprintf(filename, "MOD%d.MUS", music); + f.open(filename); + if (f.isOpen() == false) + error("playMusic: Can't load music from '%s'", filename); + _midi.setLoop(true); // Must do this BEFORE loading music. (GMF may have its own override.) - // Support for compressed music from the ScummVM Music Enhancement Project - AudioCD.stop(); - AudioCD.play(music + 1, -1, 0, 0); - if (AudioCD.isPlaying()) - return; + if (getFeatures() & GF_DEMO) + _midi.loadS1D(&f); + else + _midi.loadSMF(&f, music); - if (getGameId() == GID_SIMON1ACORN) { - // TODO: Add support for Desktop Tracker format - } else if (getPlatform() == Common::kPlatformAmiga) { - loadModule(music); - } else if (getFeatures() & GF_TALKIE) { - // WORKAROUND: For a script bug in the CD versions - // We skip this music resource, as it was replaced by - // a sound effect, and the script was never updated. - if (music == 35) - return; + _midi.startTrack(0); + _midi.startTrack(track); + } +} - _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET); - _gameFile->read(buf, 4); - if (!memcmp(buf, "GMF\x1", 4)) { - _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET); - _midi.loadSMF(_gameFile, music); - } else { - _gameFile->seek(_gameOffsetsPtr[_musicIndexBase + music], SEEK_SET); - _midi.loadMultipleSMF(_gameFile); - } - - _midi.startTrack(0); - } else { - char filename[15]; - File f; - sprintf(filename, "MOD%d.MUS", music); - f.open(filename); - if (f.isOpen() == false) - error("loadMusic: Can't load music from '%s'", filename); - - if (getFeatures() & GF_DEMO) - _midi.loadS1D(&f); - else - _midi.loadSMF(&f, music); +void AGOSEngine::playMusic(uint16 music, uint16 track) { + stopMusic(); - _midi.startTrack(0); - } + if (getPlatform() == Common::kPlatformAmiga) { + playModule(music); + } else if (getPlatform() == Common::kPlatformAtariST) { + // TODO: Add support for music formats used } else { - if (getPlatform() == Common::kPlatformAmiga) { - loadModule(music); - } else if (getPlatform() == Common::kPlatformAtariST) { - // TODO: Add support for music formats used - } else { - _midi.stop(); - _midi.setLoop(true); // Must do this BEFORE loading music. + _midi.setLoop(true); // Must do this BEFORE loading music. - char filename[15]; - File f; - sprintf(filename, "MOD%d.MUS", music); - f.open(filename); - if (f.isOpen() == false) - error("loadMusic: Can't load music from '%s'", filename); - - _midi.loadS1D(&f); - _midi.startTrack(0); - } + char filename[15]; + File f; + sprintf(filename, "MOD%d.MUS", music); + f.open(filename); + if (f.isOpen() == false) + error("playMusic: Can't load music from '%s'", filename); + + _midi.loadS1D(&f); + _midi.startTrack(0); + _midi.startTrack(track); } } -void AGOSEngine::playSting(uint a) { +void AGOSEngine::stopMusic() { + if (_midiEnabled) { + _midi.stop(); + } + _mixer->stopHandle(_modHandle); +} + +void AGOSEngine::playSting(uint16 soundId) { if (!_midi._enable_sfx) return; @@ -262,13 +279,13 @@ void AGOSEngine::playSting(uint a) { if (!mus_file.isOpen()) error("playSting: Can't load sound effect from '%s'", filename); - mus_file.seek(a * 2, SEEK_SET); + mus_file.seek(soundId * 2, SEEK_SET); mus_offset = mus_file.readUint16LE(); if (mus_file.ioFailed()) - error("playSting: Can't read sting %d offset", a); + error("playSting: Can't read sting %d offset", soundId); mus_file.seek(mus_offset, SEEK_SET); - _midi.loadSMF(&mus_file, a, true); + _midi.loadSMF(&mus_file, soundId, true); _midi.startTrack(0); } @@ -284,7 +301,7 @@ static const byte elvira1_soundTable[100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -bool AGOSEngine::loadVGASoundFile(uint id, uint type) { +bool AGOSEngine::loadVGASoundFile(uint16 id, uint8 type) { File in; char filename[15]; byte *dst; diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp index f7c0254c4f..af1bd0fe93 100644 --- a/engines/agos/rooms.cpp +++ b/engines/agos/rooms.cpp @@ -351,7 +351,7 @@ void AGOSEngine_Elvira2::setSRExit(Item *i, int n, int d, uint16 s) { } // Waxworks specific -bool AGOSEngine::loadRoomItems(uint item) { +bool AGOSEngine::loadRoomItems(uint16 item) { byte *p; uint i, min_num, max_num; char filename[30]; diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp index 1267e27daa..eb2266550a 100644 --- a/engines/agos/saveload.cpp +++ b/engines/agos/saveload.cpp @@ -109,7 +109,7 @@ void AGOSEngine::quickLoadOrSave() { setBitFlag(7, false); sub = getSubroutineByID(19); startSubroutine(sub); - //oe2_printStats(); + printStats(); sub = getSubroutineByID(28); startSubroutine(sub); setBitFlag(17, false); @@ -146,7 +146,171 @@ void AGOSEngine::quickLoadOrSave() { _saveLoadType = 0; } -void AGOSEngine::listSaveGames(char *dst) { +bool AGOSEngine::confirmOverWrite(WindowBlock *window) { + if (getGameType() == GType_WW) { + Subroutine *sub = getSubroutineByID(80); + if (sub != NULL) + startSubroutineEx(sub); + + if (_variableArray[253] == 0) + return true; + } else if (getGameType() == GType_ELVIRA2) { + // Original verison never confirmed + return true; + } else if (getGameType() == GType_ELVIRA1) { + const char *message1, *message2, *message3; + + switch (_language) { + case Common::FR_FRA: + message1 = "\rFichier d/j; existant.\r\r"; + message2 = " Ecrire pardessus ?\r\r"; + message3 = " Oui Non"; + break; + case Common::DE_DEU: + message1 = "\rDatei existiert bereits.\r\r"; + message2 = " berschreiben ?\r\r"; + message3 = " Ja Nein"; + break; + default: + message1 = "\r File already exists.\r\r"; + message2 = " Overwrite it ?\r\r"; + message3 = " Yes No"; + break; + } + + printScroll(); + window->textColumn = 0; + window->textRow = 0; + window->textColumnOffset = 0; + window->textLength = 0; // Difference + + for (; *message1; message1++) + windowPutChar(window, *message1); + for (; *message2; message2++) + windowPutChar(window, *message2); + for (; *message3; message3++) + windowPutChar(window, *message3); + + if (confirmYesOrNo(120, 78) == 0x7FFF) + return true; + } + + return false; +} + +int16 AGOSEngine::matchSaveGame(const char *name, uint16 max) { + Common::InSaveFile *in; + char dst[8]; + uint16 slot; + + for (slot = 0; slot < max; slot++) { + if ((in = _saveFileMan->openForLoading(genSaveName(slot)))) { + in->read(dst, 8); + delete in; + + if (!scumm_stricmp(name, dst)) { + return slot; + } + } + } + + return -1; +} + +void AGOSEngine::userGame(bool load) { + WindowBlock *window = _windowArray[4]; + const char *message1; + int i, numSaveGames; + char *name; + char buf[8]; + + numSaveGames = countSaveGames(); + + time_t saveTime = time(NULL); + haltAnimation(); + +restart: + printScroll(); + window->textColumn = 0; + window->textRow = 0; + window->textColumnOffset = 0; + window->textLength = 0; // Difference + + switch (_language) { + case Common::FR_FRA: + message1 = "\rIns/rez disquette de\rsauvegarde de jeux &\rentrez nom de fichier:\r\r "; + break; + case Common::DE_DEU: + message1 = "\rLege Spielstandsdiskette ein. Dateinamen eingeben:\r\r "; + break; + default: + message1 = "\r Insert savegame data disk & enter filename:\r\r "; + break; + } + + for (; *message1; message1++) + windowPutChar(window, *message1); + + memset(buf, 0, 8); + name = buf; + _saveGameNameLen = 0; + + for (;;) { + windowPutChar(window, 128); + _keyPressed = 0; + + for (;;) { + delay(10); + if (_keyPressed && _keyPressed < 128) { + i = _keyPressed; + break; + } + } + + userGameBackSpace(_windowArray[4], 8); + if (i == 10 || i == 13) { + break; + } else if (i == 8) { + // do_backspace + if (_saveGameNameLen) { + _saveGameNameLen--; + name[_saveGameNameLen] = 0; + userGameBackSpace(_windowArray[4], 8); + } + } else if (i >= 32 && _saveGameNameLen != 8) { + name[_saveGameNameLen++] = i; + windowPutChar(_windowArray[4], i); + } + } + + if (_saveGameNameLen != 0) { + int16 slot = matchSaveGame(name, numSaveGames); + if (!load) { + if (slot >= 0 && !confirmOverWrite(window)) + goto restart; + + if (slot < 0) + slot = numSaveGames; + + if (!saveGame(slot, name)) + fileError(_windowArray[4], true); + } else { + if (slot < 0) { + fileError(_windowArray[4], false); + } else { + if (!loadGame(genSaveName(slot))) + fileError(_windowArray[4], false); + } + } + + printStats(); + } + + restartAnimation(); + _gameStoppedClock = time(NULL) - saveTime + _gameStoppedClock; +} + +void AGOSEngine_Elvira2::listSaveGames(char *dst) { Common::InSaveFile *in; uint y, slot; @@ -166,7 +330,7 @@ void AGOSEngine::listSaveGames(char *dst) { slot = _saveLoadRowCurPos; for (y = 0; y < 8; y++) { window->textColumn = 0; - window->textColumnOffset = 4; + window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0; window->textLength = 0; if ((in = _saveFileMan->openForLoading(genSaveName(slot++)))) { in->read(dst, 8); @@ -180,8 +344,13 @@ void AGOSEngine::listSaveGames(char *dst) { } dst+= 8; - window->textColumn = 7; - window->textColumnOffset = 4; + if (getGameType() == GType_WW) { + window->textColumn = 7; + window->textColumnOffset = 4; + } else if (getGameType() == GType_ELVIRA2) { + window->textColumn = 8; + window->textColumnOffset = 0; + } window->textLength = 0; if ((in = _saveFileMan->openForLoading(genSaveName(slot++)))) { in->read(dst, 8); @@ -196,7 +365,7 @@ void AGOSEngine::listSaveGames(char *dst) { dst+= 8; window->textColumn = 15; - window->textColumnOffset = 4; + window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0; window->textLength = 0; if ((in = _saveFileMan->openForLoading(genSaveName(slot++)))) { in->read(dst, 8); @@ -221,7 +390,7 @@ void AGOSEngine::listSaveGames(char *dst) { _saveGameNameLen = 0; } -void AGOSEngine::userGame(bool load) { +void AGOSEngine_Elvira2::userGame(bool load) { time_t saveTime; int i, numSaveGames; char *name; @@ -246,6 +415,8 @@ void AGOSEngine::userGame(bool load) { if (!load) { WindowBlock *window = _windowArray[num]; + int16 slot = -1; + name = buf + 192; for (;;) { @@ -256,15 +427,9 @@ void AGOSEngine::userGame(bool load) { i = userGameGetKey(&b, buf, 128); if (b) { if (i <= 223) { - if (getGameType() == GType_WW) { - Subroutine *sub = getSubroutineByID(80); - if (sub != NULL) - startSubroutineEx(sub); - - if (_variableArray[253] != 0) { - listSaveGames(buf); - continue; - } + if (!confirmOverWrite(window)) { + listSaveGames(buf); + continue; } if (!saveGame(_saveLoadRowCurPos + i, buf + i * 8)) @@ -275,9 +440,16 @@ void AGOSEngine::userGame(bool load) { } userGameBackSpace(_windowArray[num], 8); - if (i == 10 || i == 13) + if (i == 10 || i == 13) { + slot = matchSaveGame(name, numSaveGames); + if (slot >= 0) { + if (!confirmOverWrite(window)) { + listSaveGames(buf); + continue; + } + } break; - if (i == 8) { + } else if (i == 8) { // do_backspace if (_saveGameNameLen) { _saveGameNameLen--; @@ -290,8 +462,13 @@ void AGOSEngine::userGame(bool load) { } } - if (!saveGame(numSaveGames, buf + 192)) - fileError(_windowArray[num], true); + if (_saveGameNameLen != 0) { + if (slot < 0) + slot = numSaveGames; + + if (!saveGame(slot, buf + 192)) + fileError(_windowArray[num], true); + } } else { i = userGameGetKey(&b, buf, 128); if (i != 225) { @@ -309,7 +486,7 @@ get_out:; restartAnimation(); } -int AGOSEngine::userGameGetKey(bool *b, char *buf, uint maxChar) { +int AGOSEngine_Elvira2::userGameGetKey(bool *b, char *buf, uint maxChar) { HitArea *ha; *b = true; @@ -359,26 +536,29 @@ void AGOSEngine_Simon1::listSaveGames(char *dst) { if (!(in = _saveFileMan->openForLoading(genSaveName(slot)))) break; - in->read(dst, 8); + in->read(dst, 18); delete in; lastSlot = slot; if (slot < 10) { showMessageFormat(" "); + } else if (_language == Common::HB_ISR) { + lastSlot = (slot % 10) * 10; + lastSlot += slot / 10; } + showMessageFormat("%d", lastSlot); if (_language == Common::HB_ISR && !(slot % 10)) showMessageFormat("0"); - showMessageFormat("%d", lastSlot); showMessageFormat(".%s\n", dst); dst += 18; slot++; } if (!_saveOrLoad) { - if (_saveLoadRowCurPos + 6 == slot) + if (_saveLoadRowCurPos + 6 == slot) { slot++; - else { + } else { if (slot < 10) showMessageFormat(" "); showMessageFormat("%d.\n", slot); @@ -532,9 +712,9 @@ restart:; } userGameBackSpace(_windowArray[5], 8); - if (i == 10 || i == 13) + if (i == 10 || i == 13) { break; - if (i == 8) { + } else if (i == 8) { // do_backspace if (_saveGameNameLen) { byte m, x; @@ -732,7 +912,16 @@ void AGOSEngine::fileError(WindowBlock *window, bool save_error) { } } - windowPutChar(window, 0xC); + if (getGameType() == GType_ELVIRA1) { + printScroll(); + window->textColumn = 0; + window->textRow = 0; + window->textColumnOffset = 0; + window->textLength = 0; // Difference + } else { + windowPutChar(window, 12); + } + for (; *message1; message1++) windowPutChar(window, *message1); for (; *message2; message2++) @@ -954,7 +1143,9 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) { return false; } - if (getGameType() == GType_FF) { + if (getGameType() == GType_PP) { + // No caption + } else if (getGameType() == GType_FF) { f->read(ident, 100); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { f->read(ident, 18); @@ -1104,7 +1295,9 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) { return false; } - if (getGameType() == GType_FF) { + if (getGameType() == GType_PP) { + // No caption + } else if (getGameType() == GType_FF) { f->write(caption, 100); curTime = time(NULL); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp index 8a4457faf2..c5cf6c5872 100644 --- a/engines/agos/script.cpp +++ b/engines/agos/script.cpp @@ -156,7 +156,7 @@ void AGOSEngine::o_gtf() { void AGOSEngine::o_chance() { // 23: chance - uint a = getVarOrWord(); + int16 a = getVarOrWord(); if (a == 0) { setScriptCondition(false); @@ -173,7 +173,7 @@ void AGOSEngine::o_chance() { if (a <= 0) { _chanceModifier = 0; setScriptCondition(false); - } else if ((uint)_rnd.getRandomNumber(99) < a) { + } else if ((int16)_rnd.getRandomNumber(99) < a) { if (_chanceModifier <= 0) _chanceModifier -= 5; else @@ -410,7 +410,7 @@ void AGOSEngine::o_process() { void AGOSEngine::o_when() { // 76: add timeout - uint timeout = getVarOrWord(); + uint16 timeout = getVarOrWord(); addTimeEvent(timeout, getVarOrWord()); } @@ -453,7 +453,7 @@ void AGOSEngine::o_haltAnimation() { if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { VgaTimerEntry *vte = _vgaTimerList; while (vte->delay) { - if (vte->type == 0) + if (vte->type == ANIMATE_EVENT) vte->delay += 10; vte++; } @@ -508,7 +508,14 @@ void AGOSEngine::o_picture() { return; } - _picture8600 = (vga_res == 8600); + if (getGameType() == GType_PP && getGameId() != GID_DIMP) { + if (vga_res == 8700 && getBitFlag(107)) { + _vgaPeriod = 30; + } + + _picture8600 = (vga_res == 8600); + } + setWindowImageEx(mode, vga_res); } @@ -722,13 +729,12 @@ void AGOSEngine::o_doClassIcons() { void AGOSEngine::o_playTune() { // 127: play tune - int music = getVarOrWord(); - int track = getVarOrWord(); + uint16 music = getVarOrWord(); + uint16 track = getVarOrWord(); if (music != _lastMusicPlayed) { _lastMusicPlayed = music; - loadMusic(music); - _midi.startTrack(track); + playMusic(music, track); } } @@ -746,16 +752,32 @@ void AGOSEngine::o_setAdjNoun() { void AGOSEngine::o_saveUserGame() { // 132: save user game - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - userGame(false); - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + if (getGameId() == GID_SIMON1CD32) { + // The Amiga CD32 version of Simon the Sorcerer 1uses a single slot + if (!saveGame(0, "Default Saved Game")) { + vc33_setMouseOn(); + fileError(_windowArray[5], true); + } + } else { + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + userGame(false); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + } } void AGOSEngine::o_loadUserGame() { // 133: load user game - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - userGame(true); - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + if (getGameId() == GID_SIMON1CD32) { + // The Amiga CD32 version of Simon the Sorcerer 1 uses a single slot + if (!loadGame(genSaveName(0))) { + vc33_setMouseOn(); + fileError(_windowArray[5], false); + } + } else { + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + userGame(true); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + } } void AGOSEngine::o_copysf() { @@ -872,7 +894,7 @@ uint AGOSEngine::getNextVarContents() { return (uint16)readVariable(getVarWrapper()); } -uint AGOSEngine::readVariable(uint variable) { +uint AGOSEngine::readVariable(uint16 variable) { if (variable >= _numVars) error("readVariable: Variable %d out of range", variable); @@ -892,7 +914,7 @@ void AGOSEngine::writeNextVarContents(uint16 contents) { writeVariable(getVarWrapper(), contents); } -void AGOSEngine::writeVariable(uint variable, uint16 contents) { +void AGOSEngine::writeVariable(uint16 variable, uint16 contents) { if (variable >= _numVars) error("writeVariable: Variable %d out of range", variable); @@ -978,7 +1000,7 @@ void AGOSEngine::sendSync(uint a) { _lockWord &= ~0x8000; } -void AGOSEngine::stopAnimate(uint a) { +void AGOSEngine::stopAnimate(uint16 a) { uint16 b = to16Wrapper(a); _lockWord |= 0x8000; _vcPtr = (byte *)&b; @@ -987,7 +1009,7 @@ void AGOSEngine::stopAnimate(uint a) { } void AGOSEngine::waitForSync(uint a) { - const uint maxCount = (getGameType() == GType_SIMON1) ? 500 : 1000; + const uint maxCount = (getGameType() == GType_SIMON1) ? 1000 : 2500; if (getGameType() == GType_SIMON1 && (getFeatures() & GF_TALKIE)) { if (a != 200) { diff --git a/engines/agos/script_e1.cpp b/engines/agos/script_e1.cpp index 06c347f391..b003a7262f 100644 --- a/engines/agos/script_e1.cpp +++ b/engines/agos/script_e1.cpp @@ -370,8 +370,8 @@ void AGOSEngine_Elvira1::setupOpcodes() { OPCODE(o_setAdjNoun), OPCODE(oe1_zoneDisk), /* 268 */ - OPCODE(oe1_saveUserGame), - OPCODE(oe1_loadUserGame), + OPCODE(o_saveUserGame), + OPCODE(o_loadUserGame), OPCODE(oe1_printStats), OPCODE(oe1_stopTune), /* 272 */ @@ -707,8 +707,8 @@ void AGOSEngine_Elvira1::oe1_loadGame() { uint16 stringId = getNextStringID(); debug(0, "oe1_loadGame: stub (%s)", (const char *)getStringPtrByID(stringId)); - if (!scumm_stricmp(getFileName(GAME_RESTFILE), (const char *)getStringPtrByID(stringId))) { - loadGame(getFileName(GAME_RESTFILE), true); + if (!scumm_stricmp("START", (const char *)getStringPtrByID(stringId))) { + loadGame("START", true); } else { loadGame((const char *)getStringPtrByID(stringId)); } @@ -843,20 +843,16 @@ void AGOSEngine_Elvira1::oe1_ifTime() { void AGOSEngine_Elvira1::oe1_playTune() { // 264: play tune - int music = getVarOrWord(); - int track = getVarOrWord(); + uint16 music = getVarOrWord(); + uint16 track = getVarOrWord(); if (music != _lastMusicPlayed) { _lastMusicPlayed = music; // No tune under water if (music == 4) { - if (getPlatform() == Common::kPlatformAmiga) - _mixer->stopHandle(_modHandle); - else - _midi.stop(); + stopMusic(); } else { - loadMusic(music); - _midi.startTrack(track); + playMusic(music, track); } } } @@ -867,72 +863,9 @@ void AGOSEngine_Elvira1::oe1_zoneDisk() { getVarOrWord(); } -void AGOSEngine_Elvira1::oe1_saveUserGame() { - // TODO -} - -void AGOSEngine_Elvira1::oe1_loadUserGame() { - // TODO -} - void AGOSEngine_Elvira1::oe1_printStats() { // 270: print stats - WindowBlock *window = _dummyWindow; - int val; - - window->flags = 1; - - mouseOff(); - - // Strength - val = _variableArray[0]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 5, 133, 6, val); - - // Resolution - val = _variableArray[1]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 11, 133, 6, val); - - // Dexterity - val = _variableArray[2]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 18, 133, 0, val); - - // Skill - val = _variableArray[3]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 24, 133, 0, val); - - // Life - val = _variableArray[5]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 30, 133, 2, val); - - // Experience - val = _variableArray[6]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 36, 133, 4, val); - - mouseOn(); + printStats(); } void AGOSEngine_Elvira1::oe1_stopTune() { @@ -1021,7 +954,7 @@ restart: for (; *message2; message2++) windowPutChar(window, *message2); - if (confirmQuit() == 0x7FFF) { + if (confirmYesOrNo(120, 62) == 0x7FFF) { shutdown(); } else { goto restart; @@ -1108,12 +1041,12 @@ l1: i = derefItem(i->next); } } -uint AGOSEngine::confirmQuit() { +uint AGOSEngine::confirmYesOrNo(uint16 x, uint16 y) { HitArea *ha; ha = findEmptyHitArea(); - ha->x = 120; - ha->y = 62; + ha->x = x; + ha->y = y; ha->width = 30; ha->height = 12; ha->flags = kBFBoxInUse; @@ -1122,8 +1055,8 @@ uint AGOSEngine::confirmQuit() { ha->window = 0; ha = findEmptyHitArea(); - ha->x = 180; - ha->y = 62; + ha->x = x + 60; + ha->y = y; ha->width = 24; ha->height = 12; ha->flags = kBFBoxInUse; @@ -1207,25 +1140,73 @@ uint AGOSEngine::continueOrQuit() { } void AGOSEngine::printScroll() { - VC10_state state; VgaPointersEntry *vpe = &_vgaBufferPointers[1]; + byte *curVgaFile2Orig = _curVgaFile2; + + _windowNum = 3; + _curVgaFile2 = vpe->vgaFile2; + drawImage_init(9, 0, 10, 32, 0); + + _curVgaFile2 = curVgaFile2Orig; +} + +void AGOSEngine::printStats() { + WindowBlock *window = _dummyWindow; + int val; + + window->flags = 1; + + mouseOff(); + + // Strength + val = _variableArray[0]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 5, 133, 6, val); + + // Resolution + val = _variableArray[1]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 11, 133, 6, val); - state.srcPtr = vpe->vgaFile2 + READ_BE_UINT32(vpe->vgaFile2 + 9 * 8); + // Dexterity + val = _variableArray[2]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 18, 133, 0, val); + + // Skill + val = _variableArray[3]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 24, 133, 0, val); - state.palette = 0; - state.paletteMod = 0; - state.x = 10; - state.y = 32; - state.width = state.draw_width = 10; - state.height = state.draw_height = 72; - state.flags = kDFCompressed; - _windowNum = 3; + // Life + val = _variableArray[5]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 30, 133, 2, val); - state.depack_cont = -0x80; - state.x_skip = 0; - state.y_skip = 0; + // Experience + val = _variableArray[6]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 36, 133, 4, val); - drawImage(&state); + mouseOn(); } } // End of namespace AGOS diff --git a/engines/agos/script_e2.cpp b/engines/agos/script_e2.cpp index 13cb15a8b9..00f0848ed9 100644 --- a/engines/agos/script_e2.cpp +++ b/engines/agos/script_e2.cpp @@ -145,7 +145,7 @@ void AGOSEngine_Elvira2::setupOpcodes() { OPCODE(o_comment), /* 88 */ OPCODE(o_invalid), - OPCODE(oe1_loadGame), + OPCODE(oe2_loadGame), OPCODE(o_getParent), OPCODE(o_getNext), /* 92 */ @@ -315,6 +315,17 @@ void AGOSEngine_Elvira2::oe2_pObj() { showMessageFormat("%s\n", (const char *)getStringPtrByID(subObject->objectFlagValue[0])); // Difference } +void AGOSEngine_Elvira2::oe2_loadGame() { + // 89: load game + uint16 stringId = getNextStringID(); + + if (!scumm_stricmp(getFileName(GAME_RESTFILE), (const char *)getStringPtrByID(stringId))) { + loadGame(getFileName(GAME_RESTFILE), true); + } else { + loadGame((const char *)getStringPtrByID(stringId)); + } +} + void AGOSEngine_Elvira2::oe2_drawItem() { // 113: draw item Item *i = getNextItemPtr(); @@ -498,48 +509,7 @@ void AGOSEngine_Elvira2::oe2_ink() { void AGOSEngine_Elvira2::oe2_printStats() { // 161: print stats - WindowBlock *window = _dummyWindow; - int val; - const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 131 : 134; - - window->flags = 1; - - mouseOff(); - - // Level - val = _variableArray[20]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 10, y, 0, val); - - // PP - val = _variableArray[22]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 16, y, 6, val); - - // HP - val = _variableArray[23]; - if (val < -99) - val = -99; - if (val > 99) - val = 99; - writeChar(window, 23, y, 4, val); - - // Experience - val = _variableArray[21]; - if (val < -99) - val = -99; - if (val > 9999) - val = 9999; - writeChar(window, 30, y, 6, val / 100); - writeChar(window, 32, y, 2, val / 10); - - mouseOn(); + printStats(); } void AGOSEngine_Elvira2::oe2_setSuperRoom() { @@ -697,4 +667,49 @@ void AGOSEngine_Elvira2::oe2_b2NotZero() { setScriptCondition((_bitArrayTwo[bit / 16] & (1 << (bit & 15))) != 0); } +void AGOSEngine_Elvira2::printStats() { + WindowBlock *window = _dummyWindow; + int val; + const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 131 : 134; + + window->flags = 1; + + mouseOff(); + + // Level + val = _variableArray[20]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 10, y, 0, val); + + // PP + val = _variableArray[22]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 16, y, 6, val); + + // HP + val = _variableArray[23]; + if (val < -99) + val = -99; + if (val > 99) + val = 99; + writeChar(window, 23, y, 4, val); + + // Experience + val = _variableArray[21]; + if (val < -99) + val = -99; + if (val > 9999) + val = 9999; + writeChar(window, 30, y, 6, val / 100); + writeChar(window, 32, y, 2, val / 10); + + mouseOn(); +} + } // End of namespace AGOS diff --git a/engines/agos/script_ff.cpp b/engines/agos/script_ff.cpp index db36d6f736..c3e6dc5192 100644 --- a/engines/agos/script_ff.cpp +++ b/engines/agos/script_ff.cpp @@ -303,7 +303,7 @@ void AGOSEngine_Feeble::executeOpcode(int opcode) { void AGOSEngine_Feeble::off_chance() { // 23 - uint a = getVarOrWord(); + uint16 a = getVarOrWord(); if (a == 0) { setScriptCondition(false); @@ -315,7 +315,7 @@ void AGOSEngine_Feeble::off_chance() { return; } - if ((uint)_rnd.getRandomNumber(99) < a) + if (_rnd.getRandomNumber(99) < a) setScriptCondition(true); else setScriptCondition(false); @@ -439,7 +439,7 @@ void AGOSEngine_Feeble::off_listSaveGames() { void AGOSEngine_Feeble::off_checkCD() { // 135: switch CD - uint disc = readVariable(97); + uint16 disc = readVariable(97); if (!strcmp(getExtra(), "4CD")) { _sound->switchVoiceFile(gss, disc); @@ -624,10 +624,10 @@ void AGOSEngine_Feeble::off_restartClock() { void AGOSEngine_Feeble::off_setColour() { // 195: set palette colour - uint c = getVarOrByte() * 4; - uint r = getVarOrByte(); - uint g = getVarOrByte(); - uint b = getVarOrByte(); + uint16 c = getVarOrByte() * 4; + uint8 r = getVarOrByte(); + uint8 g = getVarOrByte(); + uint8 b = getVarOrByte(); _displayPalette[c + 0] = r; _displayPalette[c + 1] = g; @@ -638,25 +638,25 @@ void AGOSEngine_Feeble::off_setColour() { void AGOSEngine_Feeble::off_b3Set() { // 196: set bit3 - uint bit = getVarOrByte(); + uint8 bit = getVarOrByte(); _bitArrayThree[bit / 16] |= (1 << (bit & 15)); } void AGOSEngine_Feeble::off_b3Clear() { // 197: clear bit3 - uint bit = getVarOrByte(); + uint8 bit = getVarOrByte(); _bitArrayThree[bit / 16] &= ~(1 << (bit & 15)); } void AGOSEngine_Feeble::off_b3Zero() { // 198: is bit3 clear - uint bit = getVarOrByte(); + uint8 bit = getVarOrByte(); setScriptCondition((_bitArrayThree[bit / 16] & (1 << (bit & 15))) == 0); } void AGOSEngine_Feeble::off_b3NotZero() { // 199: is bit3 set - uint bit = getVarOrByte(); + uint8 bit = getVarOrByte(); setScriptCondition((_bitArrayThree[bit / 16] & (1 << (bit & 15))) != 0); } diff --git a/engines/agos/script_pp.cpp b/engines/agos/script_pp.cpp index fd8ef9b859..a7bda53e48 100644 --- a/engines/agos/script_pp.cpp +++ b/engines/agos/script_pp.cpp @@ -72,8 +72,8 @@ void AGOSEngine_PuzzlePack::setupOpcodes() { OPCODE(o_state), /* 28 */ OPCODE(o_oflag), - OPCODE(opp_iconifyWindow), OPCODE(o_invalid), + OPCODE(opp_iconifyWindow), OPCODE(o_destroy), /* 32 */ OPCODE(opp_restoreOopsPosition), @@ -238,7 +238,7 @@ void AGOSEngine_PuzzlePack::setupOpcodes() { /* 160 */ OPCODE(oe2_ink), OPCODE(off_screenTextBox), - OPCODE(os1_screenTextMsg), + OPCODE(opp_playTune), OPCODE(o_invalid), /* 164 */ OPCODE(oe2_getDollar2), @@ -297,7 +297,7 @@ void AGOSEngine_PuzzlePack::executeOpcode(int opcode) { void AGOSEngine_PuzzlePack::opp_iconifyWindow() { // 30 - getNextItemPtr(); + getNextWord(); if (_clockStopped != 0) _gameTime += time(NULL) - _clockStopped; _clockStopped = 0; @@ -308,7 +308,7 @@ void AGOSEngine_PuzzlePack::opp_restoreOopsPosition() { // 32: restore oops position uint i; - getNextItemPtr(); + getNextWord(); if (_oopsValid) { for (i = 0; i < _numVars; i++) { @@ -328,7 +328,7 @@ void AGOSEngine_PuzzlePack::opp_restoreOopsPosition() { void AGOSEngine_PuzzlePack::opp_loadMouseImage() { // 38: load mouse image - getNextItemPtr(); + getNextWord(); getVarOrByte(); loadMouseImage(); } @@ -405,6 +405,19 @@ void AGOSEngine_PuzzlePack::opp_loadUserGame() { loadGame(genSaveName(1)); } +void AGOSEngine_PuzzlePack::opp_playTune() { + // 162: play tune + getVarOrByte(); + getVarOrByte(); + getNextWord(); + + uint16 music = (uint16)getVarOrWord(); + if (music != _lastMusicPlayed) { + _lastMusicPlayed = music; + playSpeech(music, 1); + } +} + void AGOSEngine_PuzzlePack::opp_saveOopsPosition() { // 173: save oops position if (!isVgaQueueEmpty()) { diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp index e104013cae..93b907e688 100644 --- a/engines/agos/script_s1.cpp +++ b/engines/agos/script_s1.cpp @@ -374,12 +374,12 @@ void AGOSEngine_Simon1::os1_screenTextMsg() { uint vgaSpriteId = getVarOrByte(); uint color = getVarOrByte(); uint stringId = getNextStringID(); - const byte *string_ptr = NULL; + const byte *stringPtr = NULL; uint speechId = 0; TextLocation *tl; if (stringId != 0xFFFF) - string_ptr = getStringPtrByID(stringId); + stringPtr = getStringPtrByID(stringId); if (getFeatures() & GF_TALKIE) { if (getGameType() == GType_FF || getGameType() == GType_PP) @@ -399,14 +399,14 @@ void AGOSEngine_Simon1::os1_screenTextMsg() { stopAnimateSimon2(2, vgaSpriteId + 2); } - if (string_ptr != NULL && (speechId == 0 || _subtitles)) - printScreenText(vgaSpriteId, color, (const char *)string_ptr, tl->x, tl->y, tl->width); + if (stringPtr != NULL && stringPtr[0] != 0 && (speechId == 0 || _subtitles)) + printScreenText(vgaSpriteId, color, (const char *)stringPtr, tl->x, tl->y, tl->width); } void AGOSEngine_Simon1::os1_playEffect() { // 163: play sound - uint soundId = getVarOrWord(); + uint16 soundId = getVarOrWord(); if (getGameId() == GID_SIMON1DOS) playSting(soundId); @@ -450,7 +450,7 @@ void AGOSEngine_Simon1::os1_screenTextPObj() { } stringPtr = buf; } - if (stringPtr != NULL) + if (stringPtr != NULL && stringPtr[0] != 0) printScreenText(vgaSpriteId, color, stringPtr, tl->x, tl->y, tl->width); } } @@ -512,7 +512,7 @@ void AGOSEngine_Simon1::os1_scnTxtLongText() { uint speechId = 0; TextLocation *tl; - const char *string_ptr = (const char *)getStringPtrByID(_longText[stringId]); + const char *stringPtr = (const char *)getStringPtrByID(_longText[stringId]); if (getFeatures() & GF_TALKIE) speechId = _longSound[stringId]; @@ -522,8 +522,8 @@ void AGOSEngine_Simon1::os1_scnTxtLongText() { if (_speech && speechId != 0) playSpeech(speechId, vgaSpriteId); - if (string_ptr != NULL && _subtitles) - printScreenText(vgaSpriteId, color, string_ptr, tl->x, tl->y, tl->width); + if (stringPtr != NULL && stringPtr[0] != 0 && _subtitles) + printScreenText(vgaSpriteId, color, stringPtr, tl->x, tl->y, tl->width); } void AGOSEngine_Simon1::os1_mouseOn() { diff --git a/engines/agos/script_s2.cpp b/engines/agos/script_s2.cpp index 9041a99662..dfc1200d7c 100644 --- a/engines/agos/script_s2.cpp +++ b/engines/agos/script_s2.cpp @@ -323,8 +323,8 @@ void AGOSEngine_Simon2::os2_animate() { void AGOSEngine_Simon2::os2_stopAnimate() { // 99: kill sprite - uint a = getVarOrWord(); - uint b = getVarOrWord(); + uint16 a = getVarOrWord(); + uint16 b = getVarOrWord(); stopAnimateSimon2(a, b); } @@ -469,7 +469,7 @@ void AGOSEngine_Simon2::os2_waitMark() { waitForMark(i); } -void AGOSEngine::stopAnimateSimon2(uint a, uint b) { +void AGOSEngine::stopAnimateSimon2(uint16 a, uint16 b) { uint16 items[2]; items[0] = to16Wrapper(a); diff --git a/engines/agos/script_ww.cpp b/engines/agos/script_ww.cpp index 690a717acf..377b49ae3f 100644 --- a/engines/agos/script_ww.cpp +++ b/engines/agos/script_ww.cpp @@ -147,7 +147,7 @@ void AGOSEngine_Waxworks::setupOpcodes() { OPCODE(o_comment), /* 88 */ OPCODE(o_invalid), - OPCODE(oe1_loadGame), + OPCODE(oe2_loadGame), OPCODE(o_getParent), OPCODE(o_getNext), /* 92 */ diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp index a4de624ec0..7165e3cbff 100644 --- a/engines/agos/sound.cpp +++ b/engines/agos/sound.cpp @@ -34,6 +34,7 @@ #include "sound/adpcm.h" #include "sound/audiostream.h" #include "sound/flac.h" +#include "sound/mixer.h" #include "sound/mp3.h" #include "sound/voc.h" #include "sound/vorbis.h" @@ -55,11 +56,11 @@ protected: public: BaseSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigEndian = false); BaseSound(Audio::Mixer *mixer, File *file, uint32 *offsets, bool bigEndian = false); - void playSound(uint sound, Audio::SoundHandle *handle, byte flags, int vol = 0) { - playSound(sound, sound, handle, flags, vol); + void playSound(uint sound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0) { + playSound(sound, sound, type, handle, flags, vol); } virtual ~BaseSound(); - virtual void playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol = 0) = 0; + virtual void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0) = 0; virtual Audio::AudioStream *makeAudioStream(uint sound) { return NULL; } }; @@ -72,6 +73,7 @@ private: uint _loopSound; public: LoopingAudioStream(BaseSound *parent, uint sound, uint loopSound, bool loop); + ~LoopingAudioStream(); int readBuffer(int16 *buffer, const int numSamples); bool isStereo() const { return _stream ? _stream->isStereo() : 0; } bool endOfData() const; @@ -87,6 +89,10 @@ LoopingAudioStream::LoopingAudioStream(BaseSound *parent, uint sound, uint loopS _stream = _parent->makeAudioStream(sound); } +LoopingAudioStream::~LoopingAudioStream() { + delete _stream; +} + int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) { if (!_loop) { return _stream->readBuffer(buffer, numSamples); @@ -121,19 +127,19 @@ public: WavSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigEndian = false) : BaseSound(mixer, file, base, bigEndian) {} WavSound(Audio::Mixer *mixer, File *file, uint32 *offsets) : BaseSound(mixer, file, offsets) {} Audio::AudioStream *makeAudioStream(uint sound); - void playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol = 0); + void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0); }; class VocSound : public BaseSound { public: VocSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigEndian = false) : BaseSound(mixer, file, base, bigEndian) {} - void playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol = 0); + void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0); }; class RawSound : public BaseSound { public: RawSound(Audio::Mixer *mixer, File *file, uint32 base = 0, bool bigEndian = false) : BaseSound(mixer, file, base, bigEndian) {} - void playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol = 0); + void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0); }; BaseSound::BaseSound(Audio::Mixer *mixer, File *file, uint32 base, bool bigEndian) { @@ -236,12 +242,12 @@ Audio::AudioStream *WavSound::makeAudioStream(uint sound) { return Audio::makeWAVStream(*_file); } -void WavSound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol) { +void WavSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) { convertVolume(vol); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), sound, vol); + _mixer->playInputStream(type, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), -1, vol); } -void VocSound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol) { +void VocSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) { if (_offsets == NULL) return; @@ -250,10 +256,10 @@ void VocSound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, int size, rate; byte *buffer = Audio::loadVOCFromStream(*_file, size, rate); assert(buffer); - _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE, sound); + _mixer->playRaw(type, handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE); } -void RawSound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol) { +void RawSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) { if (_offsets == NULL) return; @@ -263,7 +269,7 @@ void RawSound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte *buffer = (byte *)malloc(size); assert(buffer); _file->read(buffer, size); - _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer, size, 22050, flags | Audio::Mixer::FLAG_AUTOFREE, sound); + _mixer->playRaw(type, handle, buffer, size, 22050, flags | Audio::Mixer::FLAG_AUTOFREE); } #ifdef USE_MAD @@ -271,7 +277,7 @@ class MP3Sound : public BaseSound { public: MP3Sound(Audio::Mixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {} Audio::AudioStream *makeAudioStream(uint sound); - void playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol = 0); + void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0); }; Audio::AudioStream *MP3Sound::makeAudioStream(uint sound) { @@ -289,9 +295,9 @@ Audio::AudioStream *MP3Sound::makeAudioStream(uint sound) { return Audio::makeMP3Stream(_file, size); } -void MP3Sound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol) { +void MP3Sound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) { convertVolume(vol); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), sound, vol); + _mixer->playInputStream(type, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), -1, vol); } #endif @@ -300,7 +306,7 @@ class VorbisSound : public BaseSound { public: VorbisSound(Audio::Mixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {} Audio::AudioStream *makeAudioStream(uint sound); - void playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol = 0); + void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0); }; Audio::AudioStream *VorbisSound::makeAudioStream(uint sound) { @@ -318,9 +324,9 @@ Audio::AudioStream *VorbisSound::makeAudioStream(uint sound) { return Audio::makeVorbisStream(_file, size); } -void VorbisSound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol) { +void VorbisSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) { convertVolume(vol); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), sound, vol); + _mixer->playInputStream(type, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), -1, vol); } #endif @@ -329,7 +335,7 @@ class FlacSound : public BaseSound { public: FlacSound(Audio::Mixer *mixer, File *file, uint32 base = 0) : BaseSound(mixer, file, base) {} Audio::AudioStream *makeAudioStream(uint sound); - void playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol = 0); + void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol = 0); }; Audio::AudioStream *FlacSound::makeAudioStream(uint sound) { @@ -347,9 +353,9 @@ Audio::AudioStream *FlacSound::makeAudioStream(uint sound) { return Audio::makeFlacStream(_file, size); } -void FlacSound::playSound(uint sound, uint loopSound, Audio::SoundHandle *handle, byte flags, int vol) { +void FlacSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) { convertVolume(vol); - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), sound, vol); + _mixer->playInputStream(type, handle, new LoopingAudioStream(this, sound, loopSound, (flags & Audio::Mixer::FLAG_LOOP) != 0), -1, vol); } #endif @@ -584,19 +590,16 @@ void Sound::playVoice(uint sound) { if (!_voice) return; - if (_mixer->getSoundID(_voiceHandle) == (int)sound) - return; - _mixer->stopHandle(_voiceHandle); if (_vm->getGameType() == GType_PP) { if (sound < 11) - _voice->playSound(sound, sound + 1, &_voiceHandle, Audio::Mixer::FLAG_LOOP, -1500); + _voice->playSound(sound, sound + 1, Audio::Mixer::kMusicSoundType, &_voiceHandle, Audio::Mixer::FLAG_LOOP, -1500); else - _voice->playSound(sound, sound, &_voiceHandle, Audio::Mixer::FLAG_LOOP); + _voice->playSound(sound, sound, Audio::Mixer::kMusicSoundType, &_voiceHandle, Audio::Mixer::FLAG_LOOP); } else if (_vm->getGameType() == GType_FF || _vm->getGameId() == GID_SIMON1CD32) { - _voice->playSound(sound, &_voiceHandle, 0); + _voice->playSound(sound, Audio::Mixer::kSpeechSoundType, &_voiceHandle, 0); } else { - _voice->playSound(sound, &_voiceHandle, Audio::Mixer::FLAG_UNSIGNED); + _voice->playSound(sound, Audio::Mixer::kSpeechSoundType, &_voiceHandle, Audio::Mixer::FLAG_UNSIGNED); } } @@ -607,7 +610,7 @@ void Sound::playEffects(uint sound) { if (_effectsPaused) return; - _effects->playSound(sound, &_effectsHandle, (_vm->getGameId() == GID_SIMON1CD32) ? 0 : Audio::Mixer::FLAG_UNSIGNED); + _effects->playSound(sound, Audio::Mixer::kSFXSoundType, &_effectsHandle, (_vm->getGameId() == GID_SIMON1CD32) ? 0 : Audio::Mixer::FLAG_UNSIGNED); } void Sound::playAmbient(uint sound) { @@ -623,7 +626,7 @@ void Sound::playAmbient(uint sound) { return; _mixer->stopHandle(_ambientHandle); - _effects->playSound(sound, &_ambientHandle, Audio::Mixer::FLAG_LOOP | Audio::Mixer::FLAG_UNSIGNED); + _effects->playSound(sound, Audio::Mixer::kSFXSoundType, &_ambientHandle, Audio::Mixer::FLAG_LOOP | Audio::Mixer::FLAG_UNSIGNED); } bool Sound::hasVoice() const { @@ -669,13 +672,16 @@ void Sound::ambientPause(bool b) { // Elvira 1/2 and Waxworks specific void Sound::playRawData(byte *soundData, uint sound, uint size) { + if (_effectsPaused) + return; + byte *buffer = (byte *)malloc(size); memcpy(buffer, soundData, size); if (_vm->getPlatform() == Common::kPlatformPC) - _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, 8000, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE, sound); + _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, 8000, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE); else - _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, 8000, Audio::Mixer::FLAG_AUTOFREE, sound); + _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, 8000, Audio::Mixer::FLAG_AUTOFREE); } // Feeble Files specific @@ -739,7 +745,7 @@ void Sound::playSoundData(Audio::SoundHandle *handle, byte *soundData, uint soun memcpy(buffer, soundData + stream.pos(), size); } - _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE, sound, vol, pan); + _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE, -1, vol, pan); } void Sound::stopSfx5() { diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp index 8c5e911c39..483f101889 100644 --- a/engines/agos/string.cpp +++ b/engines/agos/string.cpp @@ -32,7 +32,7 @@ using Common::File; namespace AGOS { -const byte *AGOSEngine::getStringPtrByID(uint stringId) { +const byte *AGOSEngine::getStringPtrByID(uint16 stringId) { const byte *string_ptr; byte *dst; @@ -49,7 +49,7 @@ const byte *AGOSEngine::getStringPtrByID(uint stringId) { return dst; } -const byte *AGOSEngine::getLocalStringByID(uint stringId) { +const byte *AGOSEngine::getLocalStringByID(uint16 stringId) { if (stringId < _stringIdLocalMin || stringId >= _stringIdLocalMax) { loadTextIntoMem(stringId); } @@ -140,7 +140,7 @@ uint AGOSEngine::loadTextFile_gme(const char *filename, byte *dst) { return size; } -void AGOSEngine::loadTextIntoMem(uint stringId) { +void AGOSEngine::loadTextIntoMem(uint16 stringId) { byte *p; char filename[30]; int i; @@ -304,7 +304,7 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin lettersPerRowJustified = stringLength / (stringLength / lettersPerRow + 1) + 1; talkDelay = (stringLength + 3) / 3; - if ((getGameType() == GType_SIMON1) && (getFeatures() & GF_TALKIE)) { + if (getGameType() == GType_SIMON1 && (getFeatures() & GF_TALKIE)) { if (_variableArray[141] == 0) _variableArray[141] = 9; _variableArray[85] = _variableArray[141] * talkDelay; @@ -364,16 +364,16 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin renderString(vgaSpriteId, color, width, height, convertedString); } - int b = (!getBitFlag(133)) ? 3 : 4; + uint16 windowNum = (!getBitFlag(133)) ? 3 : 4; x /= 8; if (y < 2) y = 2; if (getGameType() == GType_SIMON1) - animate(b, 2, vgaSpriteId + 199, x, y, 12); + animate(windowNum, 2, 199 + vgaSpriteId, x, y, 12); else - animate(b, 2, vgaSpriteId, x, y, 12); + animate(windowNum, 2, vgaSpriteId, x, y, 12); } // The Feeble Files specific diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp index a92f01db2b..f4a6ba3266 100644 --- a/engines/agos/subroutine.cpp +++ b/engines/agos/subroutine.cpp @@ -288,7 +288,7 @@ File *AGOSEngine::openTablesFile_gme(const char *filename) { return _gameFile; } -bool AGOSEngine::loadTablesIntoMem(uint subr_id) { +bool AGOSEngine::loadTablesIntoMem(uint16 subr_id) { byte *p; uint16 min_num, max_num, file_num; File *in; @@ -337,7 +337,7 @@ bool AGOSEngine::loadTablesIntoMem(uint subr_id) { return 0; } -bool AGOSEngine_Waxworks::loadTablesIntoMem(uint subr_id) { +bool AGOSEngine_Waxworks::loadTablesIntoMem(uint16 subr_id) { byte *p; int i; uint min_num, max_num; @@ -399,7 +399,7 @@ bool AGOSEngine_Waxworks::loadTablesIntoMem(uint subr_id) { return 0; } -bool AGOSEngine::loadXTablesIntoMem(uint subr_id) { +bool AGOSEngine::loadXTablesIntoMem(uint16 subr_id) { byte *p; int i; uint min_num, max_num; @@ -461,7 +461,7 @@ void AGOSEngine::closeTablesFile(File *in) { } } -Subroutine *AGOSEngine::createSubroutine(uint id) { +Subroutine *AGOSEngine::createSubroutine(uint16 id) { Subroutine *sub; alignTableMem(); @@ -681,7 +681,7 @@ void AGOSEngine::readSubroutineLine(Common::SeekableReadStream *in, SubroutineLi byte *AGOSEngine::readSingleOpcode(Common::SeekableReadStream *in, byte *ptr) { int i, l; const char *string_ptr; - uint opcode, val; + uint16 opcode, val; const char *const *table; diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp index ddb7398312..f99d6db591 100644 --- a/engines/agos/verb.cpp +++ b/engines/agos/verb.cpp @@ -26,6 +26,10 @@ // Verb and hitarea handling #include "common/stdafx.h" +#include "common/system.h" + +#include "graphics/surface.h" + #include "agos/agos.h" #include "agos/intern.h" @@ -296,6 +300,10 @@ void AGOSEngine::showActionString(const byte *string) { window->textColumn = x / 8; window->textColumnOffset = x & 7; + if (_language == Common::HB_ISR && window->textColumnOffset != 0) { + window->textColumnOffset = 8 - window->textColumnOffset; + window->textColumn++; + } for (; *string; string++) windowPutChar(window, *string); @@ -391,13 +399,15 @@ HitArea *AGOSEngine::findBox(uint hitarea_id) { HitArea *AGOSEngine::findEmptyHitArea() { HitArea *ha = _hitAreas; - uint count = ARRAYSIZE(_hitAreas); + uint count = ARRAYSIZE(_hitAreas) - 1; do { if (ha->flags == 0) return ha; } while (ha++, --count); - return NULL; + + // The last box is overwritten, if too many boxes are allocated. + return ha; } void AGOSEngine::freeBox(uint index) { @@ -674,21 +684,21 @@ void AGOSEngine::boxController(uint x, uint y, uint mode) { if (mode != 0) { if (mode == 3) { - if (getGameType() == GType_ELVIRA1) { + if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) { if (best_ha->verb & 0x4000) { - if (_variableArray[500] == 0) { + if (getGameType() == GType_ELVIRA1 && _variableArray[500] == 0) { _variableArray[500] = best_ha->verb & 0xBFFF; } - } - if (_clickOnly != 0 && best_ha->id < 8) { - uint id = best_ha->id; - if (id >= 4) - id -= 4; + if (_clickOnly != 0 && best_ha->id < 8) { + uint id = best_ha->id; + if (id >= 4) + id -= 4; - invertBox(findBox(id), 0, 0, 0, 0); - _clickOnly = 0; - return; + invertBox(findBox(id), 0, 0, 0, 0); + _clickOnly = 0; + return; + } } } @@ -826,7 +836,14 @@ void AGOSEngine::invertBox(HitArea * ha, byte a, byte b, byte c, byte d) { int w, h, i; _lockWord |= 0x8000; - src = getFrontBuf() + ha->y * _dxSurfacePitch + (ha->x - _scrollX * 8); + + Graphics::Surface *screen = _system->lockScreen(); + src = (byte *)screen->pixels + ha->y * _dxSurfacePitch + ha->x; + + // WORKAROUND: Hitareas for saved game names aren't adjusted for scrolling locations + if (getGameType() == GType_SIMON2 && ha->id >= 208 && ha->id <= 213) { + src -= _scrollX * 8; + } _litBoxFlag = true; @@ -864,6 +881,8 @@ void AGOSEngine::invertBox(HitArea * ha, byte a, byte b, byte c, byte d) { src += _dxSurfacePitch; } while (--h); + _system->unlockScreen(); + _lockWord &= ~0x8000; } diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index 1d2c280246..2b8f6d3a09 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -32,6 +32,8 @@ #include "common/system.h" +#include "graphics/surface.h" + namespace AGOS { // Opcode tables @@ -215,8 +217,8 @@ bool AGOSEngine::vc_maybe_skip_proc_1(uint16 a, int16 b) { void AGOSEngine::dirtyBackGround() { AnimTable *animTable = _screenAnim1; while (animTable->srcPtr) { - if (animTable->id == _vgaCurSpriteId) { - animTable->window |= 0x8000; + if (animTable->id == _vgaCurSpriteId && animTable->zoneNum == _vgaCurZoneNum) { + animTable->windowNum |= 0x8000; break; } animTable++; @@ -226,13 +228,8 @@ void AGOSEngine::dirtyBackGround() { VgaSprite *AGOSEngine::findCurSprite() { VgaSprite *vsp = _vgaSprites; while (vsp->id) { - if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) { - if (vsp->id == _vgaCurSpriteId && vsp->zoneNum == _vgaCurZoneNum) - break; - } else { - if (vsp->id == _vgaCurSpriteId) - break; - } + if (vsp->id == _vgaCurSpriteId && vsp->zoneNum == _vgaCurZoneNum) + break; vsp++; } return vsp; @@ -241,13 +238,8 @@ VgaSprite *AGOSEngine::findCurSprite() { bool AGOSEngine::isSpriteLoaded(uint16 id, uint16 zoneNum) { VgaSprite *vsp = _vgaSprites; while (vsp->id) { - if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) { - if (vsp->id == id && vsp->zoneNum == zoneNum) - return true; - } else { - if (vsp->id == id) - return true; - } + if (vsp->id == id && vsp->zoneNum == zoneNum) + return true; vsp++; } return false; @@ -708,12 +700,6 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, int16 x, int16 y, u } } - state.surf2_addr = getFrontBuf(); - state.surf2_pitch = _dxSurfacePitch; - - state.surf_addr = getBackBuf(); - state.surf_pitch = _dxSurfacePitch; - drawImage(&state); } @@ -804,16 +790,19 @@ void AGOSEngine::checkWaitEndTable() { } void AGOSEngine::vc17_waitEnd() { + uint16 id = vcReadNextWord(); + VgaSleepStruct *vfs = _waitEndTable; while (vfs->ident) vfs++; - vfs->ident = vcReadNextWord(); - vfs->code_ptr = _vcPtr; - vfs->sprite_id = _vgaCurSpriteId; - vfs->cur_vga_file = _vgaCurZoneNum; - - _vcPtr = (byte *)&_vc_get_out_of_code; + if (isSpriteLoaded(id, id / 100)) { + vfs->ident = id; + vfs->code_ptr = _vcPtr; + vfs->sprite_id = _vgaCurSpriteId; + vfs->cur_vga_file = _vgaCurZoneNum; + _vcPtr = (byte *)&_vc_get_out_of_code; + } } void AGOSEngine::vc18_jump() { @@ -843,10 +832,7 @@ void AGOSEngine::vc19_loop() { } void AGOSEngine::vc20_setRepeat() { - /* FIXME: This opcode is somewhat strange: it first reads a BE word from - * the script (advancing the script pointer in doing so); then it writes - * back the same word, this time as LE, into the script. - */ + // Sets counter used by the endRepeat opcode below. uint16 a = vcReadNextWord(); WRITE_LE_UINT16(const_cast<byte *>(_vcPtr), a); _vcPtr += 2; @@ -1042,7 +1028,7 @@ void AGOSEngine::vc27_resetSprite() { vte = _vgaTimerList; while (vte->delay) { // Skip the animateSprites event in earlier games - if (vte->type == 2) { + if (vte->type == ANIMATE_INT) { vte++; // For animated heart in Elvira 2 } else if (getGameType() == GType_ELVIRA2 && vte->sprite_id == 100) { @@ -1125,6 +1111,7 @@ void AGOSEngine::vc33_setMouseOn() { _displayPalette[65 * 4 + 1] = 48 * 4; _displayPalette[65 * 4 + 2] = 40 * 4; _displayPalette[65 * 4 + 3] = 0; + _paletteFlag = 1; } mouseOn(); } @@ -1136,9 +1123,7 @@ void AGOSEngine::vc34_setMouseOff() { _leftButtonDown = 0; } -void AGOSEngine::clearVideoBackGround(uint num, uint color) { - debug(0, "clearVideoBackGround: num %d color %d", num, color); - +void AGOSEngine::clearVideoBackGround(uint16 num, uint16 color) { const uint16 *vlut = &_videoWindows[num * 4]; byte *dst = getBackGround() + vlut[0] * 16 + (vlut[1] * (vlut[2] * 16)); @@ -1148,7 +1133,7 @@ void AGOSEngine::clearVideoBackGround(uint num, uint color) { } } -void AGOSEngine::clearVideoWindow(uint num, uint color) { +void AGOSEngine::clearVideoWindow(uint16 num, uint16 color) { if (getGameType() == GType_ELVIRA1) { if (num == 2 || num == 6) return; @@ -1160,13 +1145,11 @@ void AGOSEngine::clearVideoWindow(uint num, uint color) { return; } - debug(0, "clearVideoWindow: num %d color %d", num, color); - if (getGameType() == GType_SIMON2) { const uint16 *vlut = &_videoWindows[num * 4]; - uint xoffs = vlut[0] * 16; - uint yoffs = vlut[1]; - uint dstWidth = _videoWindows[18] * 16; + uint16 xoffs = vlut[0] * 16; + uint16 yoffs = vlut[1]; + uint16 dstWidth = _videoWindows[18] * 16; byte *dst = _window4BackScn + xoffs + yoffs * dstWidth; setMoveRect(0, 0, vlut[2] * 16, vlut[3]); @@ -1179,12 +1162,14 @@ void AGOSEngine::clearVideoWindow(uint num, uint color) { _window4Flag = 1; } else { if (getGameType() == GType_ELVIRA1 && num == 3) { - memset(getFrontBuf(), color, _screenWidth * _screenHeight); + Graphics::Surface *screen = _system->lockScreen(); + memset((byte *)screen->pixels, color, _screenWidth * _screenHeight); + _system->unlockScreen(); } else if (num == 4) { const uint16 *vlut = &_videoWindows[num * 4]; - uint xoffs = (vlut[0] - _videoWindows[16]) * 16; - uint yoffs = (vlut[1] - _videoWindows[17]); - uint dstWidth = _videoWindows[18] * 16; + uint16 xoffs = (vlut[0] - _videoWindows[16]) * 16; + uint16 yoffs = (vlut[1] - _videoWindows[17]); + uint16 dstWidth = _videoWindows[18] * 16; byte *dst = _window4BackScn + xoffs + yoffs * dstWidth; setMoveRect(0, 0, vlut[2] * 16, vlut[3]); @@ -1228,7 +1213,7 @@ void AGOSEngine::vc36_setWindowImage() { uint16 windowNum = vcReadNextWord(); if (getGameType() == GType_FF || getGameType() == GType_PP) { - _copyPartialMode = 2; + fillBackGroundFromFront(); } else { setWindowImage(windowNum, vga_res); } diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp index ca1a3a4469..a4925de842 100644 --- a/engines/agos/vga_e2.cpp +++ b/engines/agos/vga_e2.cpp @@ -31,6 +31,8 @@ #include "common/system.h" +#include "graphics/surface.h" + namespace AGOS { void AGOSEngine_Elvira2::setupVideoOpcodes(VgaOpcodeProc *op) { @@ -67,44 +69,49 @@ void AGOSEngine::vc44_ifBitClear() { } void AGOSEngine::vc45_setWindowPalette() { - uint num = vcReadNextWord(); - uint color = vcReadNextWord(); + uint16 num = vcReadNextWord(); + uint16 color = vcReadNextWord(); + + const uint16 *vlut = &_videoWindows[num * 4]; + uint8 width = vlut[2] * 8; + uint8 height = vlut[3]; if (num == 4) { - const uint16 *vlut = &_videoWindows[num * 4]; - uint16 *dst = (uint16 *)_window4BackScn; - uint width = vlut[2] * 16 / 2; - uint height = vlut[3]; - - for (uint h = 0; h < height; h++) { - for (uint w = 0; w < width; w++) { - dst[w] &= 0xF0F; - dst[w] |= color * 16; + byte *dst = _window4BackScn; + + for (uint8 h = 0; h < height; h++) { + for (uint8 w = 0; w < width; w++) { + uint16 val = READ_LE_UINT16(dst + w * 2); + val &= 0xF0F; + val |= color * 16; + WRITE_LE_UINT16(dst + w * 2, val); } - dst += width; + dst += width * 2; } } else { - const uint16 *vlut = &_videoWindows[num * 4]; - uint16 *dst = (uint16 *)getFrontBuf() + vlut[0] * 8 + vlut[1] * _dxSurfacePitch / 2; - uint width = vlut[2] * 16 / 2; - uint height = vlut[3]; + Graphics::Surface *screen = _system->lockScreen(); + byte *dst = (byte *)screen->pixels + vlut[0] * 16 + vlut[1] * _dxSurfacePitch; if (getGameType() == GType_ELVIRA2 && num == 7) { - dst -= 4; + dst -= 8; width += 4; } - for (uint h = 0; h < height; h++) { - for (uint w = 0; w < width; w++) { - dst[w] &= 0xF0F; - dst[w] |= color * 16; + for (uint8 h = 0; h < height; h++) { + for (uint8 w = 0; w < width; w++) { + uint16 val = READ_LE_UINT16(dst + w * 2); + val &= 0xF0F; + val |= color * 16; + WRITE_LE_UINT16(dst + w * 2, val); } - dst += _dxSurfacePitch / 2; + dst += _dxSurfacePitch; } + + _system->unlockScreen(); } } -void AGOSEngine::setPaletteSlot(uint srcOffs, uint dstOffs) { +void AGOSEngine::setPaletteSlot(uint16 srcOffs, uint8 dstOffs) { byte *offs, *palptr, *src; uint16 num; @@ -128,17 +135,17 @@ void AGOSEngine::setPaletteSlot(uint srcOffs, uint dstOffs) { } void AGOSEngine::vc46_setPaletteSlot1() { - uint srcOffs = vcReadNextWord(); + uint16 srcOffs = vcReadNextWord(); setPaletteSlot(srcOffs, 1); } void AGOSEngine::vc47_setPaletteSlot2() { - uint srcOffs = vcReadNextWord(); + uint16 srcOffs = vcReadNextWord(); setPaletteSlot(srcOffs, 2); } void AGOSEngine::vc48_setPaletteSlot3() { - uint srcOffs = vcReadNextWord(); + uint16 srcOffs = vcReadNextWord(); setPaletteSlot(srcOffs, 3); } @@ -211,10 +218,13 @@ void AGOSEngine::vc53_dissolveIn() { int16 xoffs = _videoWindows[num * 4 + 0] * 16; int16 yoffs = _videoWindows[num * 4 + 1]; - byte *dstPtr = getFrontBuf() + xoffs + yoffs * _screenWidth; + int16 offs = xoffs + yoffs * _screenWidth; uint16 count = dissolveCheck * 2; while (count--) { + Graphics::Surface *screen = _system->lockScreen(); + byte *dstPtr = (byte *)screen->pixels + offs; + yoffs = _rnd.getRandomNumber(dissolveY); dst = dstPtr + yoffs * _screenWidth; src = _window4BackScn + yoffs * 224; @@ -253,15 +263,15 @@ void AGOSEngine::vc53_dissolveIn() { *dst &= color; *dst |= *src & 0xF; + _system->unlockScreen(); + dissolveCount--; if (!dissolveCount) { if (count >= dissolveCheck) dissolveDelay++; dissolveCount = dissolveDelay; - _system->copyRectToScreen(getFrontBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight); - _system->updateScreen(); - delay(0); + delay(1); } } } @@ -281,11 +291,14 @@ void AGOSEngine::vc54_dissolveOut() { int16 xoffs = _videoWindows[num * 4 + 0] * 16; int16 yoffs = _videoWindows[num * 4 + 1]; - byte *dstPtr = getFrontBuf() + xoffs + yoffs * _screenWidth; - color |= dstPtr[0] & 0xF0; + int16 offs = xoffs + yoffs * _screenWidth; uint16 count = dissolveCheck * 2; while (count--) { + Graphics::Surface *screen = _system->lockScreen(); + byte *dstPtr = (byte *)screen->pixels + offs; + color |= dstPtr[0] & 0xF0; + yoffs = _rnd.getRandomNumber(dissolveY); xoffs = _rnd.getRandomNumber(dissolveX); dst = dstPtr + xoffs + yoffs * _screenWidth; @@ -304,15 +317,15 @@ void AGOSEngine::vc54_dissolveOut() { dst += xoffs; *dst = color; + _system->unlockScreen(); + dissolveCount--; if (!dissolveCount) { if (count >= dissolveCheck) dissolveDelay++; dissolveCount = dissolveDelay; - _system->copyRectToScreen(getFrontBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight); - _system->updateScreen(); - delay(0); + delay(1); } } } @@ -339,11 +352,15 @@ void AGOSEngine::vc55_moveBox() { } void AGOSEngine::vc56_fullScreen() { + Graphics::Surface *screen = _system->lockScreen(); + + byte *dst = (byte *)screen->pixels; byte *src = _curVgaFile2 + 32; - byte *dst = getFrontBuf(); memcpy(dst, src + 768, _screenHeight * _screenWidth); + _system->unlockScreen(); + //fullFade(); uint8 palette[1024]; diff --git a/engines/agos/vga_ff.cpp b/engines/agos/vga_ff.cpp index e1ee56002e..29b05e1e3c 100644 --- a/engines/agos/vga_ff.cpp +++ b/engines/agos/vga_ff.cpp @@ -217,7 +217,7 @@ void AGOSEngine::checkScrollX(int16 x, int16 xpos) { if (_scrollXMax == 0 || x == 0) return; - if ((getGameType() == GType_FF) && (getBitFlag(80) || getBitFlag(82))) + if (getGameType() == GType_FF && (getBitFlag(80) || getBitFlag(82))) return; int16 tmp; diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp index 9e482e95f4..9c05bc1100 100644 --- a/engines/agos/vga_s2.cpp +++ b/engines/agos/vga_s2.cpp @@ -52,6 +52,14 @@ void AGOSEngine_Simon2::setupVideoOpcodes(VgaOpcodeProc *op) { void AGOSEngine::vc56_delayLong() { uint16 num = vcReadVarOrWord() * _frameCount; + if (getGameType() == GType_FF && _currentTable) { + // WORKAROUND: When the repair man comes to fix the car, the game doesn't + // wait long enough for the screen to completely scroll to the left side. + if (_currentTable->id == 20438 && _vgaCurSpriteId == 13 && _vgaCurZoneNum == 2) { + num *= 2; + } + } + addVgaEvent(num + _vgaBaseDelay, ANIMATE_EVENT, _vcPtr, _vgaCurSpriteId, _vgaCurZoneNum); _vcPtr = (byte *)&_vc_get_out_of_code; } @@ -194,7 +202,7 @@ void AGOSEngine::vc72_segue() { int16 loop = vcReadNextWord(); if (track == -1 || track == 999) { - _midi.stop(); + stopMusic(); } else { _midi.setLoop(loop != 0); _midi.startTrack(track); diff --git a/engines/agos/vga_ww.cpp b/engines/agos/vga_ww.cpp index 60aeeaeebe..c24a115e71 100644 --- a/engines/agos/vga_ww.cpp +++ b/engines/agos/vga_ww.cpp @@ -31,6 +31,8 @@ #include "common/system.h" +#include "graphics/surface.h" + namespace AGOS { void AGOSEngine_Waxworks::setupVideoOpcodes(VgaOpcodeProc *op) { @@ -43,23 +45,55 @@ void AGOSEngine_Waxworks::setupVideoOpcodes(VgaOpcodeProc *op) { op[63] = &AGOSEngine::vc63_fastFadeIn; } -void AGOSEngine::vcStopAnimation(uint file, uint sprite) { - uint16 old_sprite_id, old_cur_file_id; +void AGOSEngine::vcStopAnimation(uint16 zone, uint16 sprite) { + uint16 oldCurSpriteId, oldCurZoneNum; + VgaSprite *vsp; + VgaTimerEntry *vte; + const byte *vcPtrOrg; + + oldCurSpriteId = _vgaCurSpriteId; + oldCurZoneNum = _vgaCurZoneNum; + vcPtrOrg = _vcPtr; + + _vgaCurZoneNum = zone; + _vgaCurSpriteId = sprite; + + vsp = findCurSprite(); + if (vsp->id) { + vc25_halt_sprite(); + + vte = _vgaTimerList; + while (vte->delay) { + if (vte->sprite_id == _vgaCurSpriteId && vte->cur_vga_file == _vgaCurZoneNum) { + deleteVgaEvent(vte); + break; + } + vte++; + } + } + + _vgaCurZoneNum = oldCurZoneNum; + _vgaCurSpriteId = oldCurSpriteId; + _vcPtr = vcPtrOrg; +} + +void AGOSEngine_Simon1::vcStopAnimation(uint16 zone, uint16 sprite) { + uint16 oldCurSpriteId, oldCurZoneNum; VgaSleepStruct *vfs; VgaSprite *vsp; VgaTimerEntry *vte; const byte *vcPtrOrg; - old_sprite_id = _vgaCurSpriteId; - old_cur_file_id = _vgaCurZoneNum; + oldCurSpriteId = _vgaCurSpriteId; + oldCurZoneNum = _vgaCurZoneNum; vcPtrOrg = _vcPtr; - _vgaCurZoneNum = file; + _vgaCurZoneNum = zone; _vgaCurSpriteId = sprite; vfs = _waitSyncTable; while (vfs->ident != 0) { - if (vfs->sprite_id == _vgaCurSpriteId && ((getGameType() == GType_SIMON1) || vfs->cur_vga_file == _vgaCurZoneNum)) { + if (vfs->sprite_id == _vgaCurSpriteId && vfs->cur_vga_file == _vgaCurZoneNum) { while (vfs->ident != 0) { memcpy(vfs, vfs + 1, sizeof(VgaSleepStruct)); vfs++; @@ -75,7 +109,7 @@ void AGOSEngine::vcStopAnimation(uint file, uint sprite) { vte = _vgaTimerList; while (vte->delay) { - if (vte->sprite_id == _vgaCurSpriteId && (getGameType() == GType_SIMON1 || vte->cur_vga_file == _vgaCurZoneNum)) { + if (vte->sprite_id == _vgaCurSpriteId && vte->cur_vga_file == _vgaCurZoneNum) { deleteVgaEvent(vte); break; } @@ -83,8 +117,8 @@ void AGOSEngine::vcStopAnimation(uint file, uint sprite) { } } - _vgaCurZoneNum = old_cur_file_id; - _vgaCurSpriteId = old_sprite_id; + _vgaCurZoneNum = oldCurZoneNum; + _vgaCurSpriteId = oldCurSpriteId; _vcPtr = vcPtrOrg; } @@ -98,8 +132,8 @@ void AGOSEngine::vc60_stopAnimation() { zoneNum = vcReadNextWord(); sprite = vcReadNextWord(); } else { - zoneNum = _vgaCurZoneNum; sprite = vcReadNextWord(); + zoneNum = sprite / 100; } vcStopAnimation(zoneNum, sprite); @@ -110,13 +144,15 @@ void AGOSEngine::vc61() { byte *src, *dst, *dstPtr; uint h, tmp; + Graphics::Surface *screen = _system->lockScreen(); + if (a == 6) { src = _curVgaFile2 + 800; - dstPtr = getFrontBuf(); + dstPtr = (byte *)screen->pixels; memcpy(dstPtr, src, 64000); tmp = 4 - 1; } else { - dstPtr = getFrontBuf(); + dstPtr = (byte *)screen->pixels; tmp = a - 1; } @@ -135,8 +171,10 @@ void AGOSEngine::vc61() { dst += _screenWidth; } - if (a != 6) + if (a != 6) { + _system->unlockScreen(); return; + } src = _curVgaFile2 + 9984 * 16 + 15344; } @@ -148,6 +186,8 @@ void AGOSEngine::vc61() { dst += _screenWidth; } + _system->unlockScreen(); + if (a == 6) { //fullFade(); src = _curVgaFile2 + 32; @@ -197,13 +237,11 @@ void AGOSEngine::vc62_fastFadeOut() { delay(5); } - if (getGameType() == GType_FF || getGameType() == GType_PP) { - clearSurfaces(_screenHeight); - } else if (getGameType() == GType_WW) { - memset(getFrontBuf(), 0, _screenWidth * _screenHeight); + if (getGameType() == GType_WW || getGameType() == GType_FF || getGameType() == GType_PP) { + clearSurfaces(); } else { if (_windowNum != 4) { - memset(getFrontBuf(), 0, _screenWidth * _screenHeight); + clearSurfaces(); } } } diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp index 94436b0560..d4eb7ba3fc 100644 --- a/engines/agos/window.cpp +++ b/engines/agos/window.cpp @@ -25,6 +25,10 @@ #include "common/stdafx.h" +#include "common/system.h" + +#include "graphics/surface.h" + #include "agos/agos.h" #include "agos/intern.h" @@ -60,11 +64,16 @@ WindowBlock *AGOSEngine::openWindow(uint x, uint y, uint w, uint h, uint flags, window->fill_color = fillColor; window->text_color = textColor; window->textColumn = 0; - window->textRow = 0; window->textColumnOffset = 0; - window->textMaxLength = window->width * 8 / 6; // characters are 6 pixels + window->textRow = 0; window->scrollY = 0; + // Characters are 6 pixels + if (getGameType() == GType_ELVIRA2) + window->textMaxLength = (window->width * 8 - 4) / 6; + else + window->textMaxLength = window->width * 8 / 6; + if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) clearWindow(window); @@ -103,59 +112,73 @@ void AGOSEngine::clearWindow(WindowBlock *window) { window->textColumn = 0; window->textRow = 0; - window->textColumnOffset = 0; + window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0; window->textLength = 0; window->scrollY = 0; } -void AGOSEngine::colorWindow(WindowBlock *window) { +void AGOSEngine_Feeble::colorWindow(WindowBlock *window) { byte *dst; - uint h, w; + uint16 h, w; _lockWord |= 0x8000; - if (getGameType() == GType_FF || getGameType() == GType_PP) { - dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x; + dst = getBackGround() + _dxSurfacePitch * window->y + window->x; - for (h = 0; h < window->height; h++) { - for (w = 0; w < window->width; w++) { - if (dst[w] == 113 || dst[w] == 116 || dst[w] == 252) - dst[w] = window->fill_color; - } - dst += _screenWidth; + for (h = 0; h < window->height; h++) { + for (w = 0; w < window->width; w++) { + if (dst[w] == 113 || dst[w] == 116 || dst[w] == 252) + dst[w] = window->fill_color; } - } else { - dst = getFrontBuf() + _dxSurfacePitch * (window->y) + window->x * 8; - h = window->height * 8; - w = window->width * 8; - - if (getGameType() == GType_ELVIRA2 && window->y == 146) { - if (window->fill_color == 1) { - _displayPalette[33 * 4 + 0] = 48 * 4; - _displayPalette[33 * 4 + 1] = 40 * 4; - _displayPalette[33 * 4 + 2] = 32 * 4; - } else { - _displayPalette[33 * 4 + 0] = 56 * 4; - _displayPalette[33 * 4 + 1] = 56 * 4; - _displayPalette[33 * 4 + 2] = 40 * 4; - } + dst += _screenWidth; + } - dst -= _dxSurfacePitch; - h += 2; + _lockWord &= ~0x8000; +} - _paletteFlag = 1; +void AGOSEngine::colorWindow(WindowBlock *window) { + uint16 y, h; + + y = window->y; + h = window->height * 8; + + if (getGameType() == GType_ELVIRA2 && window->y == 146) { + if (window->fill_color == 1) { + _displayPalette[33 * 4 + 0] = 48 * 4; + _displayPalette[33 * 4 + 1] = 40 * 4; + _displayPalette[33 * 4 + 2] = 32 * 4; + } else { + _displayPalette[33 * 4 + 0] = 56 * 4; + _displayPalette[33 * 4 + 1] = 56 * 4; + _displayPalette[33 * 4 + 2] = 40 * 4; } - uint8 color = window->fill_color; - if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) - color += dst[0] & 0xF0; + y--; + h += 2; - do { - memset(dst, color, w); - dst += _dxSurfacePitch; - } while (--h); + _paletteFlag = 1; } + colorBlock(window, window->x * 8, y, window->width * 8, h); +} + +void AGOSEngine::colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, uint16 h) { + _lockWord |= 0x8000; + + Graphics::Surface *screen = _system->lockScreen(); + byte *dst = (byte *)screen->pixels + y * _screenWidth + x; + + uint8 color = window->fill_color; + if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) + color += dst[0] & 0xF0; + + do { + memset(dst, color, w); + dst += _screenWidth; + } while (--h); + + _system->unlockScreen(); + _lockWord &= ~0x8000; } @@ -180,29 +203,50 @@ void AGOSEngine::restoreWindow(WindowBlock *window) { } else if (getGameType() == GType_SIMON1) { restoreBlock(window->y + window->height * 8 + ((window == _windowArray[2]) ? 1 : 0), (window->x + window->width) * 8, window->y, window->x * 8); } else { - restoreBlock(window->y + window->height * 8, (window->x + window->width) * 8, window->y, window->x * 8); + uint16 x = window->x; + uint16 w = window->width; + + if (getGameType() == GType_ELVIRA1) { + // Adjustments to remove inventory arrows + if (x & 1) { + x--; + w++; + } + if (w & 1) { + w++; + } + } + + restoreBlock(window->y + window->height * 8, (x + w) * 8, window->y, x * 8); } _lockWord &= ~0x8000; } -void AGOSEngine::restoreBlock(uint h, uint w, uint y, uint x) { +void AGOSEngine::restoreBlock(uint16 h, uint16 w, uint16 y, uint16 x) { byte *dst, *src; uint i; - dst = getFrontBuf(); + Graphics::Surface *screen = _system->lockScreen(); + dst = (byte *)screen->pixels; src = getBackGround(); dst += y * _dxSurfacePitch; src += y * _dxSurfacePitch; + uint8 paletteMod = 0; + if (getGameType() == GType_ELVIRA1 && !(getFeatures() & GF_DEMO) && y >= 133) + paletteMod = 16; + while (y < h) { for (i = x; i < w; i++) - dst[i] = src[i]; + dst[i] = src[i] + paletteMod; y++; dst += _dxSurfacePitch; src += _dxSurfacePitch; } + + _system->unlockScreen(); } void AGOSEngine::setTextColor(uint color) { diff --git a/engines/agos/zones.cpp b/engines/agos/zones.cpp index 05643a6e89..a1de03e66c 100644 --- a/engines/agos/zones.cpp +++ b/engines/agos/zones.cpp @@ -44,7 +44,7 @@ void AGOSEngine::unfreezeBottom() { _vgaFrozenBase = _vgaRealBase; } -void AGOSEngine::loadZone(uint zoneNum) { +void AGOSEngine::loadZone(uint16 zoneNum) { VgaPointersEntry *vpe; CHECK_BOUNDS(zoneNum, _vgaBufferPointers); |
