/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef PRIVATE_H #define PRIVATE_H #include "common/random.h" #include "common/serializer.h" #include "engines/engine.h" #include "graphics/managed_surface.h" #include "graphics/wincursor.h" #include "video/smk_decoder.h" #include "video/subtitles.h" #include "private/grammar.h" namespace Common { class Archive; } namespace Image { class ImageDecoder; } namespace Graphics { class ManagedSurface; } struct ADGameDescription; namespace Private { enum PRIVATEActions { kActionSkip, }; // debug channels enum { kPrivateDebugFunction = 1, kPrivateDebugCode, kPrivateDebugScript, }; // sounds const int kPaperShuffleSound[7] = {32, 33, 34, 35, 36, 37, 39}; // police const int kPoliceBustVideos[6] = {1, 2, 4, 5, 7, 8}; // points const int kOriginZero[2] = {0, 0}; const int kOriginOne[2] = {64, 48}; // vm extern Gen::VM *Gen::g_vm; // structs typedef struct ExitInfo { Common::String nextSetting; Common::Rect rect; Common::String cursor; void clear() { nextSetting.clear(); rect.setEmpty(); cursor.clear(); } } ExitInfo; typedef struct MaskInfo { Graphics::Surface *surf; Common::String nextSetting; Common::Point point; Symbol *flag1; Symbol *flag2; Common::String cursor; Common::String inventoryItem; bool useBoxCollision; Common::Rect box; MaskInfo() { clear(); } void clear() { surf = nullptr; useBoxCollision = false; box = Common::Rect(); flag1 = nullptr; flag2 = nullptr; nextSetting.clear(); cursor.clear(); point = Common::Point(); inventoryItem.clear(); } } MaskInfo; enum PhoneStatus : byte { kPhoneStatusWaiting, kPhoneStatusAvailable, kPhoneStatusCalling, kPhoneStatusMissed, kPhoneStatusAnswered }; typedef struct Sound { Common::String name; Audio::SoundHandle handle; } Sound; typedef struct PhoneInfo { Common::String name; bool once; int startIndex; int endIndex; Common::String flagName; int flagValue; PhoneStatus status; int callCount; uint32 soundIndex; Common::Array sounds; } PhoneInfo; typedef struct RadioClip { Common::String name; bool played; int priority; int disabledPriority1; // 0 == none bool exactPriorityMatch1; int disabledPriority2; // 0 == none bool exactPriorityMatch2; Common::String flagName; int flagValue; } RadioClip; typedef struct Radio { Common::String path; Sound *sound; Common::Array clips; int channels[3]; Radio() : sound(nullptr) { clear(); } void clear() { clips.clear(); for (uint i = 0; i < ARRAYSIZE(channels); i++) { channels[i] = -1; } } } Radio; typedef struct DossierInfo { Common::String page1; Common::String page2; } DossierInfo; typedef struct CursorInfo { Common::String name; Common::String aname; Graphics::Cursor *cursor; Graphics::WinCursorGroup *winCursorGroup; } CursorInfo; typedef struct MemoryInfo { Common::String image; Common::String movie; } MemoryInfo; typedef struct DiaryPage { Common::String locationName; Common::Array memories; int locationID; } DiaryPage; typedef struct InventoryItem { Common::String diaryImage; Common::String flag; } InventoryItem; // funcs typedef struct FuncTable { void (*func)(Private::ArgArray); const char *name; } FunctTable; typedef Common::HashMap NameToPtr; extern const FuncTable funcTable[]; // lists typedef Common::List ExitList; typedef Common::List MaskList; typedef Common::List PhoneList; typedef Common::List InvList; typedef Common::List RectList; // arrays typedef Common::Array DossierArray; typedef Common::Array DiaryPages; // hash tables typedef Common::HashMap PlayedMediaTable; enum SubtitleType { kSubtitleAudio, kSubtitleVideo }; struct SubtitleSlot { Audio::SoundHandle handle; Video::Subtitles *subs; SubtitleSlot() : subs(nullptr) {} }; class PrivateEngine : public Engine { private: Common::RandomSource *_rnd; Graphics::PixelFormat _pixelFormat; Image::ImageDecoder *_image; int _screenW, _screenH; // helper to generate the correct subtitle path Common::Path getSubtitlePath(const Common::String &soundName); bool isSfxSubtitle(const Video::Subtitles *subs); bool isSlotActive(const SubtitleSlot &slot); public: bool _shouldHighlightMasks; bool _highlightMasks; PrivateEngine(OSystem *syst, const ADGameDescription *gd); ~PrivateEngine(); const ADGameDescription *_gameDescription; bool isDemo() const; Common::Language _language; Common::Platform _platform; SymbolMaps maps; Video::SmackerDecoder *_videoDecoder; Video::SmackerDecoder *_pausedVideo; Common::String _pausedMovieName; Common::Error run() override; void restartGame(); void clearAreas(); void initializePath(const Common::FSNode &gamePath) override; void pauseEngineIntern(bool pause) override; Common::SeekableReadStream *loadAssets(); Common::Archive *loadMacInstaller(); // Functions NameToPtr _functions; void initFuncs(); // User input void selectPauseGame(Common::Point); bool selectMask(Common::Point); bool selectExit(Common::Point); bool selectLoadGame(Common::Point); bool selectSaveGame(Common::Point); void resumeGame(); // Cursors void updateCursor(Common::Point); bool cursorPauseMovie(Common::Point); bool cursorExit(Common::Point); bool cursorSafeDigit(Common::Point); bool cursorMask(Common::Point); bool hasFeature(EngineFeature f) const override; bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; } bool canSaveAutosaveCurrently() override { return false; } bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return true; } Common::Error loadGameStream(Common::SeekableReadStream *stream) override; Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override; static Common::Path convertPath(const Common::String &name); static Common::String getVideoViewScreen(Common::String video); void playVideo(const Common::String &); void skipVideo(); void destroyVideo(); void loadSubtitles(const Common::Path &path, SubtitleType type, Sound *sound = nullptr); // use to clean up sounds which have finished playing once void updateSubtitles(); void destroySubtitles(); void adjustSubtitleSize(); Video::Subtitles *_videoSubtitles; SubtitleSlot _voiceSlot; // high priority (speech) SubtitleSlot _sfxSlot; // low priority (sfxs) bool _useSubtitles; bool _sfxSubtitles; Graphics::Surface *decodeImage(const Common::String &file, byte **palette, bool *isNewPalette); //byte *decodePalette(const Common::String &name); void remapImage(uint16 ncolors, const Graphics::Surface *oldImage, const byte *oldPalette, Graphics::Surface *newImage, const byte *currentPalette); static uint32 findMaskTransparentColor(const byte *palette, uint32 defaultColor); static void swapImageColors(Graphics::Surface *image, byte *palette, uint32 a, uint32 b); void loadImage(const Common::String &file, int x, int y); void drawScreenFrame(const byte *videoPalette); // Cursors Graphics::Cursor *_defaultCursor; Common::Array _cursors; Common::String _currentCursor; void changeCursor(const Common::String &); Common::String getInventoryCursor(); Common::String getExitCursor(); void loadCursors(); // Rendering Graphics::ManagedSurface *_compositeSurface; Graphics::Surface *loadMask(const Common::String &, int, int, bool); void loadMaskAndInfo(MaskInfo *m, const Common::String &name, int x, int y, bool drawn); void drawMask(Graphics::Surface *); void fillRect(uint32, Common::Rect); bool inMask(Graphics::Surface *, Common::Point); uint32 _transparentColor; Common::Rect _screenRect; Common::String _framePath; Graphics::Surface *_frameImage; Graphics::Surface *_mframeImage; byte *_framePalette; Common::String _nextVS; Common::String _currentVS; Common::Point _origin; void drawScreen(); bool _needToDrawScreenFrame; // settings Common::String _nextSetting; Common::String _pausedSetting; Common::String _currentSetting; Common::String getPauseMovieSetting(); Common::String getGoIntroSetting(); Common::String getMainDesktopSetting(); Common::String getDiaryTOCSetting(); Common::String getDiaryMiddleSetting(); Common::String getDiaryLastPageSetting(); Common::String getPOGoBustMovieSetting(); Common::String getPoliceBustFromMOSetting(); Common::String getListenToPhoneSetting(); Common::String getAlternateGameVariable(); Common::String getPoliceIndexVariable(); Common::String getWallSafeValueVariable(); Common::String getPoliceArrivedVariable(); Common::String getBeenDowntownVariable(); Common::String getPoliceStationLocation(); const char *getSymbolName(const char *name, const char *strippedName, const char *demoName = nullptr); // movies Common::String _nextMovie; Common::String _currentMovie; // Dossiers DossierArray _dossiers; uint _dossierSuspect; uint _dossierPage; MaskInfo _dossierPageMask; MaskInfo _dossierNextSuspectMask; MaskInfo _dossierPrevSuspectMask; MaskInfo _dossierNextSheetMask; MaskInfo _dossierPrevSheetMask; bool selectDossierPage(Common::Point); bool selectDossierNextSuspect(Common::Point); bool selectDossierPrevSuspect(Common::Point); bool selectDossierNextSheet(Common::Point); bool selectDossierPrevSheet(Common::Point); void addDossier(Common::String &page1, Common::String &page2); void loadDossier(); // Police Bust bool _policeBustEnabled; bool _policeSirenPlayed; int _numberOfClicks; int _numberClicksAfterSiren; int _policeBustMovieIndex; Common::String _policeBustMovie; Common::String _policeBustPreviousSetting; void resetPoliceBust(); void startPoliceBust(); void stopPoliceBust(); void wallSafeAlarm(); void completePoliceBust(); void checkPoliceBust(); // Diary InvList inventory; bool inInventory(const Common::String &bmp) const; void addInventory(const Common::String &bmp, Common::String &flag); void removeInventory(const Common::String &bmp); void removeRandomInventory(); Common::String _diaryLocPrefix; void loadLocations(const Common::Rect &); void loadInventory(uint32, const Common::Rect &, const Common::Rect &); bool _toTake; bool _haveTakenItem; DiaryPages _diaryPages; int _currentDiaryPage; ExitInfo _diaryNextPageExit; ExitInfo _diaryPrevPageExit; bool selectDiaryNextPage(Common::Point mousePos); bool selectDiaryPrevPage(Common::Point mousePos); void addMemory(const Common::String &path); void loadMemories(const Common::Rect &rect, uint rightPageOffset, uint verticalOffset); bool selectLocation(const Common::Point &mousePos); Common::Array _locationMasks; Common::Array _memoryMasks; bool selectMemory(const Common::Point &mousePos); void setLocationAsVisited(Symbol *location); int getMaxLocationValue(); bool selectSkipMemoryVideo(Common::Point mousePos); // Save/Load games MaskInfo _saveGameMask; MaskInfo _loadGameMask; int _mode; bool _modified; PlayedMediaTable _playedMovies; Common::String _repeatedMovieExit; // Masks/Exits ExitList _exits; MaskList _masks; // Sounds void playBackgroundSound(const Common::String &name); void playForegroundSound(const Common::String &name); void playForegroundSound(Sound &sound, const Common::String &name); void playSound(Sound &sound, const Common::String &name, bool loop); void stopForegroundSounds(); void stopSounds(); void stopSound(Sound &sound); bool isSoundPlaying(); bool isSoundPlaying(Sound &sound); void waitForSoundsToStop(); bool consumeEvents(); Sound _bgSound; Sound _fgSounds[4]; Sound _phoneCallSound; Sound _AMRadioSound; Sound _policeRadioSound; Sound _takeLeaveSound; bool _noStopSounds; Common::String _pausedBackgroundSoundName; Common::String getPaperShuffleSound(); Common::String _globalAudioPath; Common::String getTakeSound(); Common::String getTakeLeaveSound(); Common::String getLeaveSound(); Common::String _sirenSound; // Radios MaskInfo _AMRadioArea; MaskInfo _policeRadioArea; Radio _AMRadio; Radio _policeRadio; void addRadioClip( Radio &radio, const Common::String &name, int priority, int disabledPriority1, bool exactPriorityMatch1, int disabledPriority2, bool exactPriorityMatch2, const Common::String &flagName, int flagValue); void initializeAMRadioChannels(uint clipCount); void initializePoliceRadioChannels(); void disableRadioClips(Radio &radio, int priority); void playRadio(Radio &radio, bool randomlyDisableClips); bool selectAMRadioArea(Common::Point); bool selectPoliceRadioArea(Common::Point); // Phone MaskInfo _phoneArea; Common::String _phonePrefix; PhoneList _phones; void addPhone(const Common::String &name, bool once, int startIndex, int endIndex, const Common::String &flagName, int flagValue); void initializePhoneOnDesktop(); void checkPhoneCall(); bool cursorPhoneArea(Common::Point mousePos); bool selectPhoneArea(Common::Point mousePos); // Safe Common::String _safeNumberPath; MaskInfo _safeDigitArea[3]; Common::Rect _safeDigitRect[3]; void initializeWallSafeValue(); bool selectSafeDigit(Common::Point); void addSafeDigit(uint32, Common::Rect*); int getSafeDigit(uint32 d); void incrementSafeDigit(uint32 d); // Random values bool getRandomBool(uint); // Timer Common::String _timerSetting; Common::String _timerSkipSetting; uint32 _timerStartTime; uint32 _timerDelay; void setTimer(uint32 duration, const Common::String &setting, const Common::String &skipSetting); void clearTimer(); void skipTimer(); void checkTimer(); // VM objects RectList _rects; // created by fCRect }; extern PrivateEngine *g_private; } // End of namespace Private #endif