Files
2026-02-02 04:50:13 +01:00

532 lines
14 KiB
C++

/* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef TOT_H
#define TOT_H
#include "common/error.h"
#include "common/events.h"
#include "common/fs.h"
#include "common/hash-str.h"
#include "common/memstream.h"
#include "common/random.h"
#include "common/scummsys.h"
#include "common/serializer.h"
#include "common/system.h"
#include "common/util.h"
#include "engines/engine.h"
#include "engines/savestate.h"
#include "graphics/screen.h"
#include "tot/chrono.h"
#include "tot/detection.h"
#include "tot/events.h"
#include "tot/graphics.h"
#include "tot/mouse.h"
#include "tot/sound.h"
#include "tot/types.h"
namespace Tot {
struct TotGameDescription;
enum TotAction {
kActionEscape,
kActionVolume,
kActionSaveLoad,
kActionTalk,
kActionPickup,
kActionLookAt,
kActionUse,
kActionOpen,
kActionClose,
kActionYes,
kActionNo
};
class TotEngine : public Engine {
private:
Common::RandomSource _randomSource;
void handleEvent(Common::Event e);
/**
* Uses a serializer to allow implementing savegame
* loading and saving using a single method
*/
Common::Error syncGame(Common::Serializer &s);
int engineStart();
int startGame();
void newGame();
void resumeGame();
void changeRoom();
void loadScrollData(uint roomCode, bool rightScroll, uint horizontalPos, int scrollCorrection);
void drawText(uint number);
void displayLoading();
void runaroundRed();
void sprites(bool drawCharacter);
SavedGame *saveGameToRegister();
void originalSaveLoadScreen();
void loadGame(SavedGame *game);
RoomFileRegister *readScreenDataFile(Common::SeekableReadStream *screenDataFile);
void lookAtObject(byte objectNumber);
void useInventoryObjectWithInventoryObject(int16 obj1, int16 obj2);
void pickupScreenObject();
void useScreenObject();
void openScreenObject();
void closeScreenObject();
void action();
void handleAction(byte invPos);
void loadInventory();
void obtainName(Common::String &playerName);
void calculateRoute(byte zone1, byte zone2, bool extraCorrection = false, bool zonavedada = false);
void wcScene();
void advanceAnimations(bool barredZone, bool animateMouse);
void updateSecondaryAnimationDepth();
void updateMainCharacterDepth();
void actionLineText(const Common::String &actionLine);
void initializeObjectFile();
void saveObjectsData(ScreenObject *object, Common::SeekableWriteStream *out);
void scrollLeft(uint horizontalPos);
void scrollRight(uint horizontalPos);
TextEntry readTextRegister(uint numRegister);
void readConversationFile();
void adjustKey();
void adjustKey2();
void animateBat();
void updateVideo();
void nicheAnimation(byte nicheDir, int32 bitmap);
void replaceBackpack(byte obj1, uint obj2);
void dropObjectInScreen(ScreenObject *replacementObject);
void calculateTrajectory(uint finalX, uint finalY);
void animatedSequence(uint numSequence);
void initScreenPointers();
void loadAnimation(const Common::String &animation);
void loadCharAnimation();
void animateGive(uint dir, uint height);
void animatePickup1(uint dir, uint height);
void animatePickup2(uint dir, uint height);
void animateOpen2(uint dir, uint height);
void loadTV();
void loadScreen();
void loadScreenLayerWithDepth(uint coordx, uint coordy, uint bitmapSize, int32 bitmapIndex, uint depth);
void loadScreenLayer(uint coordx, uint coordy, uint picSize, int32 pic, uint prof);
void readBitmap(int32 bitmapOffset, byte *bitmap, uint bitmapSize, uint errorCode);
void updateAltScreen(byte altScreenNumber);
void freeInventory();
void updateInventory(byte index);
void updateObject(uint filePos);
void readObject(Common::SeekableReadStream *stream, uint objPos, ScreenObject *thisRegObj);
void saveObject(ScreenObject *object, Common::SeekableWriteStream *stream);
void saveItemRegister();
void saveTemporaryGame();
void drawLookAtItem(RoomObjectListEntry obj);
void putIcon(uint posX, uint posY, uint iconNumber);
void drawInventory(byte direction, byte limit);
void generateDiploma(Common::String &photoName);
void credits();
void checkMouseGrid();
void introduction();
void firstIntroduction();
void readAlphaGraph(Common::String &data, int length, int x, int y, byte barColor);
void readAlphaGraphSmall(Common::String &data, int length, int x, int y, byte barColor, byte textColor, Common::Event startEvent);
void displayObjectDescription(const Common::String &text);
void copyProtection();
void initialLogo();
void mainMenu(bool fade);
void exitToDOS();
void soundControls();
void sacrificeScene();
void ending();
void loadBat();
void loadDevil();
void assembleCompleteBackground(byte *image, uint coordx, uint coordy);
void assembleScreen(bool scroll = false);
void disableSecondAnimation();
void clearGame();
// vars
void initVars();
void resetGameState();
void clearVars();
void processEvents(bool &escapePressed);
void oldProcessEvents(bool &escapePressed);
protected:
// Engine APIs
Common::Error run() override;
void syncSoundSettings() override;
public:
Graphics::Screen *_screen = nullptr;
GraphicsManager *_graphics = nullptr;
SoundManager *_sound = nullptr;
MouseManager *_mouse = nullptr;
ChronoManager *_chrono = nullptr;
Tot::TotEventManager *_events = nullptr;
const ADGameDescription *_gameDescription;
bool _showMouseGrid = false;
bool _showScreenGrid = false;
bool _showGameGrid = false;
bool _drawObjectAreas = false;
Common::Language _lang = Common::ES_ESP;
Common::MemorySeekableReadWriteStream *_conversationData = nullptr;
Common::MemorySeekableReadWriteStream *_rooms = nullptr;
Common::MemorySeekableReadWriteStream *_sceneObjectsData = nullptr;
bool _roomChange = false;
bool _isTVOn = false;
bool _isVasePlaced = false;
bool _isScytheTaken = false;
bool _isTridentTaken = false;
bool _isPottersWheelDelivered = false;
bool _isMudDelivered = false;
bool _isGreenDevilDelivered = false;
bool _isRedDevilCaptured = false;
bool _isPottersManualDelivered = false;
bool _isCupboardOpen = false;
bool _isChestOpen = false;
bool _isTrapSet = false;
bool _isPeterCoughing = false;
bool _isSealRemoved = false;
bool _inGame = false;
bool _firstTimeDone = false; // Flag for first time run of the game.
bool _isIntroSeen = false;
bool _shouldQuitGame = false;
bool _startNewGame = false; // Flag to initialize game
bool _continueGame = false; // Flag to resume game
bool _isSavingDisabled = false;
bool _isDrawingEnabled = false; // true if sprites should be drawn
bool _isSecondaryAnimationEnabled = false; // Whether room has secondary animation
InventoryEntry _inventory[kInventoryIconCount]; // These are the icons currnetly in the inventory
/**
* Keeps an array of all inventory icon bitmaps
*/
byte *_inventoryIconBitmaps[kInventoryIconCount] = { nullptr };
/**
* Position within inventory
*/
byte _inventoryPosition = 0;
/**
* Animation sequences
*/
CharacterAnim _mainCharAnimation;
uint _mainCharFrameSize = 0;
SecondaryAnim _secondaryAnimation;
uint _secondaryAnimFrameSize = 0;
/**
* Currently selected action.
*/
byte _actionCode = 0;
/**
* Previously selected action.
*/
byte _oldActionCode = 0;
/**
* Number of trajectory changes
*/
byte _trajectorySteps = 0;
/**
* index of currently selected door.
*/
byte _doorIndex = 0;
/**
* 1 first part, 2 second part
*/
byte _gamePart = 1;
/**
* Number of frames of secondary animation
*/
byte _secondaryAnimationFrameCount = 0;
/**
* Number of directions of the secondary animation
*/
byte _secondaryAnimDirCount = 0;
/**
* Data protection control
*/
byte _cpCounter = 0, _cpCounter2 = 0;
/**
* Coordinates of target step
*/
byte _destinationX = 0, _destinationY = 0;
/**
* Current character facing direction
* 0: upwards
* 1: right
* 2: downwards
* 3: left
*/
byte _charFacingDirection = 0;
/**
* Width and height of secondary animation
*/
uint _secondaryAnimWidth = 0, _secondaryAnimHeight = 0;
/**
* Code of selected object in the backpack
*/
uint _backpackObjectCode = 0;
/**
* Auxiliary vars for grid update
*/
uint _oldposx = 0, _oldposy = 0;
/**
* Amplitude of movement
*/
int _element1 = 0, _element2 = 0;
/**
* Current position of the main character
*/
uint16 _characterPosX = 0, _characterPosY = 0;
/**
* Target position of the main character?
*/
int _xframe2 = 0, _yframe2 = 0;
/**
* Text map
*/
Common::File _verbFile;
/**
* Auxiliary vars with current inventory object name.
*/
Common::String _oldInventoryObjectName, _inventoryObjectName;
/**
* Name of player
*/
Common::String _characterName = "";
Common::String _decryptionKey;
/**
* State of the niches in part 2
*/
uint _niche[2][4];
RoomFileRegister *_currentRoomData = nullptr;
ScreenObject *_curObject = nullptr; // Currently selected object in the screen
/**
* New movement to execute.
*/
Route _mainRoute;
/**
* Matrix of positions for a trajectory between two points
*/
Common::Point _trajectory[300];
/**
* Longitude of the trajectory matrix.
*/
uint _trajectoryLength = 0;
/**
* Position within the trajectory matrix
*/
uint _currentTrajectoryIndex = 0;
/**
* Position within the trajectory matrix for secondary animation
*/
uint _currentSecondaryTrajectoryIndex = 0;
/**
* Screen areas
*/
byte _currentZone = 0, _targetZone = 0, _oldTargetZone = 0;
/**
* Amplitude of grid slices
*/
byte _maxXGrid = 0, _maxYGrid = 0;
/**
* capture of movement grid of secondary animation
*/
byte _movementGridForSecondaryAnim[10][10];
/**
* capture of mouse grid of secondary animation
*/
byte _mouseGridForSecondaryAnim[10][10];
/**
* movement mask for grid of secondary animation
*/
byte _maskGridSecondaryAnim[10][10];
/**
* mouse mask for grid of secondary animation
*/
byte _maskMouseSecondaryAnim[10][10];
bool _list1Complete = false,
_list2Complete = false,
_obtainedList1 = false, // whether we've been given list 1
_obtainedList2 = false; // whether we've been given list 2
/** Conversation topic unlocks */
bool _firstTimeTopicA[kCharacterCount] = { false },
_firstTimeTopicB[kCharacterCount] = { false },
_firstTimeTopicC[kCharacterCount] = { false },
_bookTopic[kCharacterCount] = { false },
_mintTopic[kCharacterCount] = { false };
bool _caves[5] = { false };
/**
* First and second lists of objects to retrieve in the game
*/
uint16 _firstList[5] = { 0 }, _secondList[5] = { 0 };
int32 _screenSize = 65520;
/**
* Frame number for the animations
*/
byte _iframe = 0, _iframe2 = 0;
/**
* Depth of screenobjects
*/
ObjectInfo _depthMap[kNumScreenOverlays];
/**
* Bitmaps of screenobjects
*/
byte *_screenLayers[kNumScreenOverlays] = { nullptr };
/**
* Current frame of main character
*/
byte *_curCharacterAnimationFrame = nullptr;
/**
* Current frame of secondary animation
*/
byte *_curSecondaryAnimationFrame = nullptr;
/**
* Pointer storing the screen as it displays on the game
*/
byte *_sceneBackground = nullptr;
/**
* Dirty patch of screen to repaint on every frame
*/
byte *_characterDirtyRect = nullptr;
/**
* Stores a copy of the background bitmap
*/
byte *_backgroundCopy = nullptr;
uint _currentRoomNumber = 0;
bool _isLoadingFromLauncher = false;
bool _saveAllowed = false;
/**
* Previous positions of the mouse within the screen grid
*/
uint _oldGridX = 0, _oldGridY = 0;
uint _curDepth = 0;
/**
* Point of origin of the area surrounding the main character.
* Calculated using the position of the character.
*/
uint16 _dirtyMainSpriteX = 0, _dirtyMainSpriteY = 0;
/**
* End point of origin of the area surrounding the main character.
* Calculated using the position of the character + dimension
*/
uint _dirtyMainSpriteX2 = 0, _dirtyMainSpriteY2 = 0;
byte *_spriteBackground = nullptr;
public:
TotEngine(OSystem *syst, const ADGameDescription *gameDesc);
~TotEngine() override;
uint32 getFeatures() const;
/**
* Returns the game Id
*/
Common::String getGameId() const;
/**
* Gets a random number
*/
uint32 getRandomNumber(uint maxNum) {
return _randomSource.getRandomNumber(maxNum);
}
bool hasFeature(EngineFeature f) const override {
return (f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime) ||
(f == kSupportsReturnToLauncher);
};
void drawFontSurface(Graphics::BgiFont &litt);
// Save/Load
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
void loadScreenData(uint screenNumber);
void clearScreenLayers();
void clearAnimation();
void buttonBorder(uint x1, uint y1, uint x2, uint y2, byte color1, byte color2, byte color3, byte color4, byte color5);
void drawMenu(byte menuNumber);
void drawLeftArrow(uint x, uint y);
void drawRightArrow(uint x, uint y);
void readTextFile();
void loadAnimationForDirection(Common::SeekableReadStream *stream, int direction);
void sayLine(uint textRef, byte textColor, byte shadowColor, uint &responseNumber, bool isWithinConversation);
void goToObject(byte zone1, byte zone2);
void readObject(uint objPos);
TextEntry readTextRegister();
void drawInventory();
void drawInventoryMask();
void setRoomTrajectories(int height, int width, TRAJECTORIES_OP op, bool fixGrids = true);
void saveRoomData(RoomFileRegister *room, Common::SeekableWriteStream *stream);
//vars
void initializeScreenFile();
};
extern TotEngine *g_engine;
#define SHOULD_QUIT ::Tot::g_engine->shouldQuit()
} // End of namespace Tot
#endif // TOT_H