Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/area_object.h"
namespace Bagel {
namespace SpaceBar {
/* Private methods*/
CBofSize CBagAreaObject::getSize() const {
return _xSize;
}
/* Public methods*/
CBagAreaObject::CBagAreaObject() {
_xObjType = AREA_OBJ;
setVisible(false);
CBagObject::setOverCursor(4);
}
CBagAreaObject::~CBagAreaObject() {
CBagAreaObject::detach();
}
ErrorCode CBagAreaObject::attach() {
return CBagObject::attach();
}
ErrorCode CBagAreaObject::detach() {
return CBagObject::detach();
}
CBofRect CBagAreaObject::getRect() {
const CBofPoint p = getPosition();
const CBofSize s = getSize();
CBofRect r = CBofRect(p, s);
return r;
}
void CBagAreaObject::setSize(const CBofSize &xSize) {
_xSize = xSize;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,53 @@
/* 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 BAGEL_BAGLIB_AREA_OBJECT_H
#define BAGEL_BAGLIB_AREA_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagAreaObject is an object that can be placed within the slide window.
*/
class CBagAreaObject : public CBagObject {
private:
CBofSize _xSize;
CBofSize getSize() const;
public:
CBagAreaObject();
~CBagAreaObject();
ErrorCode attach() override;
ErrorCode detach() override;
CBofRect getRect() override;
void setSize(const CBofSize &xSize) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,258 @@
/* 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/>.
*
*/
#include "common/engine_data.h"
#include "common/file.h"
#include "engines/engine.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/boflib/sound.h"
#include "bagel/spacebar/dialogs/next_cd_dialog.h"
#include "bagel/spacebar/dialogs/opt_window.h"
#include "bagel/spacebar/baglib/paint_table.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/boflib/debug.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/log.h"
namespace Bagel {
namespace SpaceBar {
// Initialize global variables.
//
CBofWindow *g_hackWindow;
CBagel::CBagel(const BagelReg *gameReg) {
assert(gameReg != nullptr);
registerGame(gameReg);
}
CBagel::~CBagel() {
assert(isValidObject(this));
// Release options file
release();
_szAppName[0] = '\0';
_pMainWnd = nullptr;
_gameReg = nullptr;
}
void CBagel::registerGame(const BagelReg *gameReg) {
assert(isValidObject(this));
_gameReg = gameReg;
// Init statics
g_hackWindow = nullptr;
// Use registration info to init this game object
if (gameReg != nullptr) {
// Keep application name
setAppName(gameReg->_gameName);
// Load this game's .ini file
if (gameReg->_optionFile != nullptr)
loadOptionFile(gameReg->_optionFile);
}
}
ErrorCode CBagel::setOption(const char *section, const char *option, const char *stringValue) {
assert(isValidObject(this));
return writeSetting(section, option, stringValue);
}
ErrorCode CBagel::setOption(const char *section, const char *option, int intValue) {
assert(isValidObject(this));
return writeSetting(section, option, intValue);
}
ErrorCode CBagel::getOption(const char *section, const char *option, char *stringValue, const char *defaultValue, uint32 size) {
assert(isValidObject(this));
return readSetting(section, option, stringValue, defaultValue, size);
}
ErrorCode CBagel::getOption(const char *section, const char *option, int *intValue, int defaultValue) {
assert(isValidObject(this));
return readSetting(section, option, intValue, defaultValue);
}
ErrorCode CBagel::getOption(const char *section, const char *option, bool *boolValue, int defaultValue) {
assert(isValidObject(this));
return readSetting(section, option, boolValue, defaultValue);
}
ErrorCode CBagel::initialize() {
assert(isValidObject(this));
// Game must already be registered with registerGame()
assert(_gameReg != nullptr);
CBofApp::initialize();
// Initialise engine data for the game
Common::U32String errMsg;
if (!Common::load_engine_data("bagel.dat", "", 1, 0, errMsg)) {
GUIErrorMessage("Could not find bagel.dat data file");
const Common::String msg(errMsg);
bofMessageBox("Engine Data", msg.c_str());
_errCode = ERR_FREAD;
return _errCode;
}
Common::File paintTable;
if (!paintTable.open("paint_table.txt")) {
bofMessageBox("Engine Data", "Invalid Paint Table");
_errCode = ERR_FREAD;
return _errCode;
}
PaintTable::initialize(paintTable);
getOption("UserOptions", "WrongCDRetries", &_numRetries, 20);
if (_numRetries < 1) {
_numRetries = 100;
}
logInfo("Initializing BAGEL");
// Turn off System cursor
CBofCursor::hide();
// Initialize local game paths
initLocalFilePaths();
// Child class must instantiate the Main Window
return _errCode;
}
ErrorCode CBagel::runApp() {
assert(isValidObject(this));
// The main game window must have been created by now
assert(_pMainWnd != nullptr);
return CBofApp::runApp();
}
ErrorCode CBagel::shutdown() {
assert(isValidObject(this));
logInfo("Shutting down BAGEL");
// Just in case the child class forgot to delete the main window,
// I'll do it.
delete _pMainWnd;
_pMainWnd = nullptr;
return CBofApp::shutdown();
}
ErrorCode CBagel::initLocalFilePaths() {
assert(isValidObject(this));
// Check for Installed state of game
getOption("Startup", "InstallCode", &_installCode, BAG_INSTALL_DEFAULT);
return _errCode;
}
ErrorCode CBagel::verifyCDInDrive(int diskId, const char *waveFile) {
assert(isValidObject(this));
if (_gameReg->_numberOfCDs > 0) {
char szBuf[MAX_DIRPATH];
// Find the drive that this disk is in
Common::sprintf_s(szBuf, "DISK%d", diskId);
Common::sprintf_s(szBuf, "$SBARDIR%sDISK%d", PATH_DELIMETER, diskId);
CBofString cString(szBuf, MAX_DIRPATH);
fixPathName(cString);
// If the disk is not in drive, then inform the user
int i = 0;
while (!shouldQuit() && !fileExists(cString.getBuffer())) {
// display a dialog box that tells the user to put the CD back into
// the drive, or Abort.
logInfo(buildString("Unable to find game's DiskID as '%s'", cString.getBuffer()));
if (i++ > _numRetries) {
reportError(ERR_FFIND, "Could not recover from missing CD");
break;
}
// Play the Zelda "Alias, you should insert disk 1 at this time."
if (i == 1 && waveFile != nullptr) {
BofPlaySound(waveFile, SOUND_WAVE | SOUND_ASYNCH);
}
if (g_hackWindow == nullptr) {
showNextCDDialog(_pMainWnd, diskId);
} else {
showNextCDDialog(g_hackWindow, diskId);
}
}
}
return _errCode;
}
void CBagel::showNextCDDialog(CBofWindow *parentWin, int diskId) {
CBagNextCDDialog cNextCDDialog;
// Use specified bitmap as this dialog's image
CBofPalette *pPal = nullptr;
CBofBitmap *pBmp = nullptr;
switch (diskId) {
case 1:
pBmp = SpaceBar::loadBitmap(buildSysDir("DISK1.BMP"), pPal);
break;
case 2:
pBmp = SpaceBar::loadBitmap(buildSysDir("DISK2.BMP"), pPal);
break;
case 3:
pBmp = SpaceBar::loadBitmap(buildSysDir("DISK3.BMP"), pPal);
break;
// Shouldn't ever get here
default:
assert(false);
break;
}
cNextCDDialog.setBackdrop(pBmp);
const CBofRect cRect = cNextCDDialog.getBackdrop()->getRect();
// Create the dialog box
cNextCDDialog.create("NextCD", cRect.left, cRect.top, cRect.width(), cRect.height(), parentWin);
cNextCDDialog.center();
cNextCDDialog.doModal();
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,202 @@
/* 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 BAGEL_BAGLIB_BAGEL_H
#define BAGEL_BAGLIB_BAGEL_H
#include "bagel/spacebar/boflib/app.h"
#include "bagel/spacebar/boflib/gui/window.h"
#include "bagel/spacebar/boflib/options.h"
#include "bagel/boflib/error.h"
#include "bagel/spacebar/boflib/list.h"
#include "bagel/boflib/string.h"
#include "bagel/spacebar/boflib/vhash_table.h"
namespace Bagel {
namespace SpaceBar {
// Set a default hash table size here.
// Note: Best performance is achieved if this value is a prime number!
//
#define HASH_TABLE_SIZE 131
#define MAX_APP_NAME 128
#define PATH_DELIMETER "/"
#define DISK_1 1
#define BAG_INSTALL_DEFAULT 0 /* play entire game from where it was executed */
#define HOMEDIR_TOKEN "$SBARDIR" /* Change this to $HOMEDIR */
// THE CURRENT STORAGE DEVICE OF THE GAME
#define CURRSDEV_TOKEN "$CURRENT_SDEV"
#define PREVSDEV_TOKEN "$PREVIOUS_SDEV"
// Defines default chroma color to be palette index 1
#define DEFAULT_CHROMA_COLOR 1
class CBagMasterWin;
/**
* Initialization structure fot CBagel app
*/
struct BagelReg {
const char *_gameName; // Game Name. Ex: "The Space Bar"
const char *_gamePath; // Relative path for the CD: "\\SPACEBAR"
const char *_optionFile; // This game's INI file name
const char *_saveGameFile; // Name of save game Index file.
uint32 _ramRequired; // Amount of free RAM needed to play game
int32 _numberOfCDs; // # of CDs used by this game
int _requiredDepth; // Required bits per pixel to play game
int _requiredWidth; // Minimum screen width for game
int _requiredHeight; // Minimum screen height for game
};
class CBagel : public CBofOptions, public CBofApp {
public:
CBagel(const BagelReg *gameReg);
~CBagel();
/**
* Registers game information for this game object
* @param gameReg Game registration info
*/
void registerGame(const BagelReg *gameReg);
// these functions must be provided by the child class
//
/**
* Initializes BAGEL, checks system resources, etc...
* @return Error return code
*/
ErrorCode initialize() override;
/**
* Provides main message loop (MainEventLoop)
* @return Error return Code.
*/
ErrorCode runApp() override;
/**
* Performs cleanup and destruction of Bagel object
* @return Error return Code.
*/
ErrorCode shutdown() override;
/**
* Sets specified user option in associated .INI file
* @param section .INI section to write to
* @param option Option to add/update
* @param stringValue New value of option
* @return Error return code
*/
ErrorCode setOption(const char *section, const char *option, const char *stringValue);
/**
* Sets specified user option in associated .INI file
* @param section .INI section to write to
* @param option Option to add/update
* @param intValue New value of option
* @return Error return code
*/
ErrorCode setOption(const char *section, const char *option, int intValue);
/**
* Gets specified user option from associated .INI file
* @param section .INI section to read from
* @param option Option to retrieve
* @param stringValue Buffer to hold value
* @param defaultValue Default value if option not found
* @param size Length of the stringValue buffer
* @return Error return code
*/
ErrorCode getOption(const char *section, const char *option, char *stringValue, const char *defaultValue, uint32 size);
/**
* Gets specified user option from associated .INI file
* @param section .INI section to read from
* @param option Option to retrieve
* @param intValue Buffer to hold value
* @param defaultValue Default value if option not found
* @return Error return code
*/
ErrorCode getOption(const char *section, const char *option, int *intValue, int defaultValue);
/**
* Gets specified user option from associated .INI file
* @param section .INI section to read from
* @param option Option to retrieve
* @param boolValue Buffer to hold value
* @param defaultValue Default value if option not found
* @return Error return code
*/
ErrorCode getOption(const char *section, const char *option, bool *boolValue, int defaultValue);
void setAppName(const char *newAppName) override {
Common::strcpy_s(_szAppName, newAppName);
}
CBagMasterWin *getMasterWnd() const {
return (CBagMasterWin *)_pMainWnd;
}
static CBagel *getBagApp() {
return (CBagel *)_pBofApp;
}
int getChromaColor() {
return DEFAULT_CHROMA_COLOR;
}
/**
* Checks to make sure the Game CD is in the drive
* @param diskId Disk number
* @param waveFile Filename
* @return Error return code
*/
ErrorCode verifyCDInDrive(int diskId, const char *waveFile);
static void showNextCDDialog(CBofWindow *parentWin, int diskId);
static CBofVHashTable<CBofString, HASH_TABLE_SIZE> *getCacheFileList() {
return _cacheFileList;
}
protected:
/**
* initialize full path names to files stored on local disk
* @return Error return code
*/
ErrorCode initLocalFilePaths();
// Data members
const BagelReg *_gameReg = nullptr;
int _numRetries = 20;
int _installCode = 0;
private:
static CBofVHashTable<CBofString, HASH_TABLE_SIZE> *_cacheFileList;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,597 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/base_pda.h"
#include "bagel/spacebar/baglib/event_sdev.h"
#include "bagel/spacebar/dialogs/opt_window.h"
#include "bagel/spacebar/baglib/log_msg.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/moo.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/baglib/wield.h"
namespace Bagel {
namespace SpaceBar {
// Init static members
PdaMode SBBasePda::_pdaMode;
PdaPos SBBasePda::_pdaPos;
PdaMode SBBasePda::_holdMode;
void SBBasePda::initialize() {
_pdaMode = PDA_NO_MODE;
_pdaPos = PDA_POS_UNINITIALIZED;
_holdMode = PDA_NO_MODE;
}
SBBasePda::SBBasePda(CBofWindow *parent, const CBofRect & /* xRect*/, bool activated) {
_activated = activated;
_activating = false;
_moveDist = 13;
_numMoves = 10;
_parent = parent;
_mooWnd = nullptr;
_invWnd = nullptr;
_mapWnd = nullptr;
_logWnd = nullptr;
_curDisplay = nullptr;
_holdDisplay = nullptr;
// Other classes need to know if we're zoomed
setZoomed(false);
setDeactivate(false);
}
SBBasePda::~SBBasePda() {
_invWnd = nullptr;
_mapWnd = nullptr;
_logWnd = nullptr;
_mooWnd = nullptr;
}
bool SBBasePda::hideCurDisplay() {
synchronizePdaState();
if (_curDisplay) {
// If we have an inventory window
_curDisplay->setVisible(false);
// Hold this info.
_holdDisplay = _curDisplay;
_holdMode = _pdaMode;
_curDisplay = nullptr;
_pdaMode = PDA_NO_MODE;
setPdaState();
return true;
}
return false;
}
bool SBBasePda::restoreCurDisplay() {
synchronizePdaState();
// If we saved a display
if (_holdDisplay) {
// Restore the display info.
_curDisplay = _holdDisplay;
_pdaMode = _holdMode;
_curDisplay->setVisible(true);
setPdaState();
return true;
}
return false;
}
bool SBBasePda::hideMovie() {
synchronizePdaState();
if (_mooWnd) {
// if we have an inventory window
_mooWnd->setVisible(false);
_curDisplay = nullptr;
_pdaMode = PDA_NO_MODE;
setPdaState();
return true;
}
return false;
}
bool SBBasePda::showMovie() {
synchronizePdaState();
// if we're already playing a movie, then return false
if (_pdaMode == PDA_MOO_MODE) {
return false;
}
if (_mooWnd) {
if (_curDisplay) {
// Turn off the current display
_curDisplay->setVisible(false);
}
// Save the current PDA mode so we can return to it when done.
((CBagMoo *)_mooWnd)->savePDAMode(_pdaMode);
((CBagMoo *)_mooWnd)->savePDAPosition(_pdaPos);
// Turn on the inventory
_mooWnd->setVisible(true);
// Set the current display = Inventory
_curDisplay = _mooWnd;
_pdaMode = PDA_MOO_MODE;
setPdaState();
// Set default state of movie to don't deactivate PDA
setDeactivate(false);
return true;
}
return false;
}
void SBBasePda::stopMovie(bool bResetPDA) const {
if (_mooWnd && _mooWnd == _curDisplay) {
((CBagMoo *)_mooWnd)->stopMovie(bResetPDA);
}
}
bool SBBasePda::setMovie(CBofString &movieName) const {
if (_mooWnd) {
((CBagMoo *)_mooWnd)->setPDAMovie(movieName);
return true;
}
return false;
}
bool SBBasePda::hideInventory() {
synchronizePdaState();
// if we have an inventory window
if (_invWnd) {
_invWnd->setVisible(false);
_curDisplay = nullptr;
_pdaMode = PDA_NO_MODE;
setPdaState();
return true;
}
return false;
}
bool SBBasePda::showInventory() {
synchronizePdaState();
// if a movie is playing, then stop it.
stopMovie(false);
// If we have an inventory window
if (_invWnd) {
if (_curDisplay) {
// Turn off the current display
_curDisplay->setVisible(false);
}
// Turn on the inventory
_invWnd->setVisible(true);
// Set the current display = Inventory
_curDisplay = _invWnd;
_pdaMode = PDA_INV_MODE;
setPdaState();
return true;
}
return false;
}
bool SBBasePda::showMap() {
synchronizePdaState();
// If a movie is playing, then stop it.
stopMovie(false);
// if we have a map window
if (_mapWnd) {
if (_curDisplay) {
// Turn off the current display
_curDisplay->setVisible(false);
}
// Turn on the map
_mapWnd->setVisible(true);
// Set the current display = Map
_curDisplay = _mapWnd;
_pdaMode = PDA_MAP_MODE;
_mapWnd->attachActiveObjects();
setPdaState();
return true;
}
return false;
}
bool SBBasePda::hideMap() {
synchronizePdaState();
// if we have a map window
if (_mapWnd) {
// Turn off the Map
_mapWnd->setVisible(false);
// set the current display to nullptr
_curDisplay = nullptr;
setPdaState();
_pdaMode = PDA_NO_MODE;
return true;
}
return false;
}
bool SBBasePda::showLog() {
if (CBagStorageDevWnd::_pEvtSDev != nullptr) {
CBagStorageDevWnd::_pEvtSDev->evaluateExpressions();
}
synchronizePdaState();
// If a movie is playing, then stop it.
stopMovie(false);
// if we have a map window
if (_logWnd) {
if (_curDisplay) {
// Turn off the current display
_curDisplay->setVisible(false);
}
// Turn on the map
_logWnd->setVisible(true);
// Set the current display = Map
_curDisplay = _logWnd;
_pdaMode = PDA_LOG_MODE;
_logWnd->attachActiveObjects();
setPdaState();
return true;
}
return false;
}
bool SBBasePda::msgLight() {
// If we have a map window
if (_logWnd) {
((CBagLog *)_logWnd)->playMsgQueue();
}
return true;
}
void *SBBasePda::pdaButtonHandler(int refId, void *info) {
assert(info != nullptr);
SBBasePda *curPda = (SBBasePda *)info;
switch (refId) {
case PDA_MAP:
curPda->showMap();
break;
case PDA_STASH:
curPda->showInventory();
break;
case PDA_ZOOM:
curPda->zoom();
break;
case PDA_SYSTEM: {
CBagel *curApp = CBagel::getBagApp();
if (curApp != nullptr) {
CBagMasterWin *curWnd = curApp->getMasterWnd();
if (curWnd != nullptr) {
curWnd->postUserMessage(WM_SHOW_SYSTEM_DLG, 0);
}
}
break;
}
case PDA_LOG:
curPda->showLog();
break;
case PDA_OFF:
curPda->deactivate();
break;
case PDA_MSGLIGHT:
curPda->msgLight();
break;
default:
break;
}
return info;
}
void SBBasePda::synchronizePdaState() {
if (_pdaPos == PDA_DOWN && isActivated()) {
deactivate();
} else if (_pdaPos == PDA_UP && isActivated() == false) {
activate();
}
}
void SBBasePda::activate() {
if (!_activating) {
_activating = _numMoves;
_activated = true;
}
_pdaPos = PDA_UP;
setPdaState();
}
void SBBasePda::deactivate() {
if (!_activating) {
_activating = _numMoves;
_activated = false;
}
_pdaPos = PDA_DOWN;
setPdaState();
}
void SBBasePda::setPdaState() {
const char *pdaMode;
const char *pdaPos;
CBagVar *curVar = g_VarManager->getVariable("INBAR");
if (curVar != nullptr) {
// Defined as global
pdaMode = "BARPDAMODE";
pdaPos = "BARPDAPOSITION";
} else {
pdaMode = "PDAMODE";
pdaPos = "PDAPOSITION";
}
// Save the pda state and position
curVar = g_VarManager->getVariable(pdaMode);
if (curVar != nullptr) {
switch (_pdaMode) {
case PDA_NO_MODE:
curVar->setValue("NOMODE");
break;
case PDA_MAP_MODE:
curVar->setValue("MAPMODE");
break;
case PDA_INV_MODE:
curVar->setValue("INVMODE");
break;
case PDA_LOG_MODE:
curVar->setValue("LOGMODE");
break;
case PDA_MOO_MODE:
curVar->setValue("MOOMODE");
break;
}
}
curVar = g_VarManager->getVariable(pdaPos);
if (curVar != nullptr) {
switch (_pdaPos) {
case PDA_UP:
curVar->setValue("UP");
break;
case PDA_DOWN:
curVar->setValue("DOWN");
break;
default:
break;
}
}
}
void SBBasePda::getPdaState() {
char localBuff[256];
CBofString pdaState(localBuff, 256);
const char *pdaMode;
const char *pdaPos;
CBagVar *curVar = g_VarManager->getVariable("INBAR");
if (curVar != nullptr) {
// Defined as global
pdaMode = "BARPDAMODE";
pdaPos = "BARPDAPOSITION";
} else {
pdaMode = "PDAMODE";
pdaPos = "PDAPOSITION";
}
curVar = g_VarManager->getVariable(pdaMode);
if (curVar) {
pdaState = curVar->getValue();
// Now set the internal PDA state based on this info.
// If we saved during a movie, then restore to map mode.
if (pdaState.find("MAP") != -1 || pdaState.find("MOO") != -1) {
_pdaMode = PDA_MAP_MODE;
} else if (pdaState.find("INV") != -1) {
_pdaMode = PDA_INV_MODE;
} else if (pdaState.find("LOG") != -1) {
_pdaMode = PDA_LOG_MODE;
} else if (pdaState.find("MOO") != -1) {
_pdaMode = PDA_MOO_MODE;
} else {
_pdaMode = PDA_NO_MODE;
}
}
// Get the PDA up/down position
curVar = g_VarManager->getVariable(pdaPos);
if (curVar) {
pdaState = curVar->getValue();
if (pdaState.find("UP") != -1) {
_pdaPos = PDA_UP;
} else {
_pdaPos = PDA_DOWN;
}
}
}
#define NULL_CURSOR 0
#define HAND_CURSOR 1
int SBBasePda::getProperCursor(const CBofPoint &pos, CBofRect &pdaRect) const {
const int wieldCursor = CBagWield::getWieldCursor();
// Assume can't click
const int cursorID = NULL_CURSOR;
// If we're in the map, return the nullptr cursor, if on the pda but not in the
// map window, return the hand. Same rules for nomode.
switch (_pdaMode) {
case PDA_MAP_MODE:
case PDA_NO_MODE:
case PDA_MOO_MODE:
if (_mapWnd) {
const CBofRect pdaViewRect = _mapWnd->getRect() + pdaRect.topLeft();
if (pdaViewRect.ptInRect(pos)) {
if (wieldCursor >= 0) {
return wieldCursor;
}
return NULL_CURSOR;
}
return HAND_CURSOR;
}
break;
case PDA_INV_MODE:
case PDA_LOG_MODE:
// Make sure our cur display is synchronized.
assert(_pdaMode == PDA_INV_MODE ? _curDisplay == _invWnd : _curDisplay == _logWnd);
// If we have a display, then parouse its list and see if we're over something worth
// mousedowning on.
if (_curDisplay) {
CBagObject *overObj = nullptr;
CBofRect pdaViewRect = _curDisplay->getRect() + pdaRect.topLeft();
if (pdaViewRect.ptInRect(pos)) {
// Go through the list of inventory items and see if we're over any of them
// in particular.
CBofList<CBagObject *> *objList = _curDisplay->getObjectList();
if (objList != nullptr) {
// Localize pda view rect
pdaViewRect = _curDisplay->getRect() + pdaRect.topLeft();
const int count = objList->getCount();
for (int i = 0; i < count; ++i) {
CBagObject *curObj = objList->getNodeItem(i);
if (curObj->isActive()) {
// localize icon rectangle
CBofRect iconRect = curObj->getRect() + pdaViewRect.topLeft();
if (iconRect.ptInRect(pos)) {
overObj = curObj;
}
}
}
}
if (_pdaMode == PDA_LOG_MODE) {
if (overObj) {
return overObj->getOverCursor();
}
if (wieldCursor >= 0) {
return wieldCursor;
}
}
if (_pdaMode == PDA_INV_MODE) {
if (wieldCursor >= 0) {
return wieldCursor;
}
if (overObj) {
return overObj->getOverCursor();
}
}
return NULL_CURSOR;
}
return HAND_CURSOR;
}
}
return cursorID;
}
CBofRect SBBasePda::getViewRect() const {
return (_curDisplay == nullptr ? CBofRect() : _curDisplay->getRect());
}
ErrorCode SBBasePda::attachActiveObjects() {
if (CBagStorageDevWnd::_pEvtSDev != nullptr) {
CBagStorageDevWnd::_pEvtSDev->evaluateExpressions();
}
if (_mooWnd)
_mooWnd->attachActiveObjects();
if (_invWnd)
_invWnd->attachActiveObjects();
if (_mapWnd)
_mapWnd->attachActiveObjects();
if (_logWnd)
_logWnd->attachActiveObjects();
return ERR_NONE;
}
ErrorCode SBBasePda::detachActiveObjects() {
if (_mooWnd)
_mooWnd->detachActiveObjects();
if (_invWnd)
_invWnd->detachActiveObjects();
if (_mapWnd)
_mapWnd->detachActiveObjects();
if (_logWnd)
_logWnd->detachActiveObjects();
return ERR_NONE;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,203 @@
/* 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 BAGEL_BAGLIB_BASE_PDA_H
#define BAGEL_BAGLIB_BASE_PDA_H
#include "bagel/spacebar/baglib/storage_dev_bmp.h"
namespace Bagel {
namespace SpaceBar {
#define PDA_MAP (100)
#define PDA_STASH (101)
#define PDA_ZOOM (102)
#define PDA_SYSTEM (103)
#define PDA_LOG (104)
#define PDA_OFF (105)
#define PDA_MSGLIGHT (110)
#define PDA_ZOOMFLASH "ZOOMFLASH"
enum PdaMode {
PDA_NO_MODE,
PDA_MAP_MODE,
PDA_INV_MODE,
PDA_LOG_MODE,
PDA_MOO_MODE
};
enum PdaPos {
PDA_POS_UNINITIALIZED,
PDA_UP,
PDA_DOWN
};
class SBBasePda {
protected:
// All PDA's in the game should share the same mode
static PdaMode _pdaMode;
static PdaPos _pdaPos;
int _numMoves;
int _activating;
bool _activated;
int _moveDist;
CBagStorageDevBmp *_mooWnd; // Pointer to the PDAMOVIE object
CBagStorageDevBmp *_invWnd; // Pointer to the inventory object
CBagStorageDevBmp *_mapWnd; // Pointer to the Map object
CBagStorageDevBmp *_logWnd; // Pointer to the Map object
CBagStorageDevBmp *_curDisplay; // Pointer to the object currently displayed in PDA
CBofWindow *_parent;
bool _zoomedFl;
bool _deactivateFl; // should we deactivate when done w/movie?
// hold this info for restore method
CBagStorageDevBmp *_holdDisplay;
static PdaMode _holdMode;
public:
SBBasePda(CBofWindow *parent = nullptr, const CBofRect &rect = CBofRect(), bool activated = false);
virtual ~SBBasePda();
static void initialize();
/**
* Allows PDA mode to be set by script
*/
static void setPdaMode(PdaMode pdaMode) {
_pdaMode = pdaMode;
}
static PdaMode getPdaMode() {
return _pdaMode;
}
bool isActivated() const {
return _activating ? !_activated : _activated;
}
bool isActivating() const {
return _activating;
}
virtual ErrorCode attachActiveObjects();
virtual ErrorCode detachActiveObjects();
/**
* Sync starting options
*/
void synchronizePdaState();
void activate();
void deactivate();
/**
* Show the inventory
*/
virtual bool showInventory();
/**
* Hide the inventory
*/
virtual bool hideInventory();
/**
* Show the movie window
*/
virtual bool showMovie();
/**
* Hide the movie window
*/
virtual bool hideMovie();
/**
* Set the movie to play
* @param movieName Movie filename
* @return Success/failure
*/
bool setMovie(CBofString &movieName) const;
/**
* Stops any playing movie
*/
void stopMovie(bool bResetPDA) const;
void setDeactivate(bool b) {
_deactivateFl = b;
}
bool getDeactivate() const {
return _deactivateFl;
}
/**
* Show the map
*/
virtual bool showMap();
/**
* Hide the map
*/
virtual bool hideMap();
/**
* Zoom the current display
*/
virtual bool zoom() {
return true;
}
virtual bool showLog();
virtual bool msgLight();
/**
* Hide the current display and reset the _curDisplay to nullptr
* @return Success/failure
*/
virtual bool hideCurDisplay();
/**
* Hide the current display and reset the _curDisplay to nullptr
* @return Success/Failure
*/
virtual bool restoreCurDisplay();
static void *pdaButtonHandler(int refId, void *info);
void setPdaState();
void getPdaState();
void setZoomed(bool newVal) {
_zoomedFl = newVal;
}
bool getZoomed() const {
return _zoomedFl;
}
int getProperCursor(const CBofPoint &pos, CBofRect &pdaRect) const;
/**
* Returns the background rect
*/
CBofRect getViewRect() const;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,109 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/bmp_object.h"
#include "bagel/spacebar/boflib/app.h"
namespace Bagel {
namespace SpaceBar {
CBagBmpObject::CBagBmpObject() : CBagObject() {
_xObjType = BMP_OBJ;
_bmp = nullptr;
_transparency = -1;
CBagObject::setOverCursor(1);
setTimeless(true);
}
CBagBmpObject::~CBagBmpObject() {
CBagBmpObject::detach();
}
ErrorCode CBagBmpObject::attach(CBofPalette *palette) {
_bmp = new CBofBitmap(getFileName(), palette);
return CBagObject::attach();
}
ErrorCode CBagBmpObject::detach() {
delete _bmp;
_bmp = nullptr;
return CBagObject::detach();
}
CBofRect CBagBmpObject::getRect() {
const CBofPoint curPos = getPosition();
CBofSize size;
if (_bmp)
size = _bmp->getSize();
return CBofRect(curPos, size);
}
ErrorCode CBagBmpObject::update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect, int maskColor) {
if (bmp) {
_transparency = maskColor;
if (srcRect) {
const CBofSize size = bmp->getSize();
if (pt.x < 0) {
srcRect->left -= pt.x;
pt.x = 0;
}
if (pt.y < 0) {
srcRect->top -= pt.y;
pt.y = 0;
}
int offset = srcRect->right + pt.x - size.cx;
if (offset >= 0) {
srcRect->right -= offset + 1;
}
offset = srcRect->bottom + pt.y - size.cy;
if (offset >= 0) {
srcRect->bottom -= offset + 1;
}
}
if (_bmp->paint(bmp, pt.x, pt.y, srcRect, maskColor))
return ERR_UNKNOWN;
}
return ERR_NONE;
}
bool CBagBmpObject::isInside(const CBofPoint &pt) {
if (_bmp && getRect().ptInRect(pt)) {
if (_transparency >= 0) {
const int x = pt.x - getRect().left;
const int y = pt.y - getRect().top;
const int color = _bmp->readPixel(x, y);
return color != _transparency;
}
return true;
}
return false;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,72 @@
/* 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 BAGEL_BAGLIB_BMP_OBJECT_H
#define BAGEL_BAGLIB_BMP_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagBmpObject is an object that can be place within the slide window.
*/
class CBagBmpObject : public CBagObject {
private:
CBofBitmap *_bmp;
int _transparency;
protected:
void setBitmap(CBofBitmap *bmp) {
_bmp = bmp;
}
public:
CBagBmpObject();
virtual ~CBagBmpObject();
ErrorCode attach() override {
return attach(nullptr);
}
ErrorCode attach(CBofPalette *palette);
ErrorCode detach() override;
bool isAttached() override {
return _bmp != nullptr;
}
bool isInside(const CBofPoint &pt) override;
CBofBitmap *getBitmap() const {
return _bmp;
}
CBofRect getRect() override;
ErrorCode update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect = nullptr, int maskColor = -1) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,504 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/button_object.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
namespace Bagel {
namespace SpaceBar {
CBagButtonObject::CBagButtonObject() {
_xObjType = BUTTON_OBJ;
_buttonType = BTN_PUSH;
// Set to first cel
CBagObject::setState(0);
_active = false;
_activeDown = false;
_activeUp = false;
_numPos = 0;
_dragging = false;
setCallBack(nullptr, nullptr);
setAlwaysUpdate(true);
setTimeless(true);
}
CBagButtonObject::~CBagButtonObject() {
CBagButtonObject::detach();
}
ErrorCode CBagButtonObject::attach() {
const ErrorCode errorCode = CBagSpriteObject::attach();
CBofSprite *curSprite = getSprite();
if (curSprite) {
curSprite->setAnimated(false);
}
if (_buttonType == BTN_VLEVER || _buttonType == BTN_HLEVER) {
_midPoint.x = getRect().topLeft().x + (getRect().width() / 2);
_midPoint.y = getRect().topLeft().y + (getRect().height() / 2);
}
if (curSprite && curSprite->getCelCount() == 1 && _buttonType != BTN_SLIDER) {
// Only given down state
setVisible(false);
}
// If this is a slider button make sure it is in the correct position
if (_buttonType == BTN_SLIDER) {
CBofPoint NewPoint = getPosition();
const int xIncrement = _slideRect.width() / (_numPos - 1);
NewPoint.x = _slideRect.left + (getState() * xIncrement);
setPosition(NewPoint);
}
return errorCode;
}
ErrorCode CBagButtonObject::detach() {
return CBagSpriteObject::detach();
}
extern bool g_noMenuFl;
bool CBagButtonObject::runObject() {
// Reset wield
g_noMenuFl = false;
if (_buttonType == BTN_PUSH) {
if (_active && !_activeUp) {
_activeUp = true;
}
if (getSprite() && (getSprite()->getCelCount() == 1)) {
// Only given down state
setVisible(false);
}
// Set to first cel
setState(0);
}
runCallBack();
return CBagObject::runObject();
}
void CBagButtonObject::onLButtonDown(uint32 /*nFlags*/, CBofPoint *point, void *) {
if (_buttonType == BTN_PUSH) {
if (!_active && !_activeDown) {
_activeDown = true;
_active = true;
}
if (getSprite() && (getSprite()->getCelCount() == 1)) {
// Only given down state
setVisible();
}
// Set to clicked down
setState(1);
} else if (_buttonType == BTN_HLEVER || _buttonType == BTN_VLEVER) {
if (!_activeDown && !_activeUp) {
if ((_buttonType == BTN_HLEVER && point->x > _midPoint.x) || // right of midpoint
(_buttonType == BTN_VLEVER && point->y > _midPoint.y)) { // below midpoint
_activeDown = true;
} else {
_activeUp = true;
}
}
} else if (_buttonType == BTN_SLIDER) {
_dragging = true;
}
setDirty();
}
void CBagButtonObject::onLButtonUp(uint32 flags, CBofPoint *point, void *extraInfo) {
CBagStorageDevWnd *pMainWin = (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev());
if (pMainWin != nullptr) {
pMainWin->setPreFilterPan(true);
}
if ((_buttonType == BTN_SLIDER) && _dragging) {
// Snap to place
CBofPoint NewPoint = getPosition();
// Get the mouse point relative to the pan window
CBagPanWindow *pWnd = (CBagPanWindow *)extraInfo;
const CBofRect r = pWnd->getSlideBitmap()->getCurrView();
const int mLocX = point->x + r.left - pWnd->getViewPortPos().x;
const int xIncrement = _slideRect.width() / (_numPos - 1);
int slidePos = _slideRect.left;
int i;
for (i = 0; (i < _numPos) && (slidePos < mLocX); i++)
slidePos = _slideRect.left + (i * xIncrement);
// We Went too far
i--;
// Find the previous position was closer to the mouse
if ((i > 0) && (slidePos - mLocX > mLocX - (slidePos - xIncrement)))
i--; // Go back one
NewPoint.x = _slideRect.left + (i * xIncrement);
if (NewPoint.x < _slideRect.left) {
NewPoint.x = _slideRect.left;
} else if (NewPoint.x > _slideRect.right) {
NewPoint.x = _slideRect.right;
}
setPosition(NewPoint);
if (i < 0) {
i = 0;
} else if (i >= _numPos) {
i = _numPos - 1;
}
setState(i);
_dragging = false;
} else if (_buttonType == BTN_CHECKBOX) {
if (!_active) {
_active = true;
_activeDown = !_activeDown;
if (getSprite() && (getSprite()->getCelCount() == 1)) {
// Only given down state
setVisible(_activeDown);
_active = false;
}
if (_activeDown)
setState(1);
else
setState(0);
}
}
setDirty();
CBagSpriteObject::onLButtonUp(flags, point, extraInfo);
}
bool CBagButtonObject::onMouseMove(uint32 /*nFlags*/, CBofPoint point, void *extraInfo) {
CBagStorageDevWnd *pMainWin = (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev());
if (_buttonType == BTN_SLIDER && _dragging) {
if (!_slideRect.isRectEmpty()) {
if (pMainWin != nullptr) {
pMainWin->setPreFilterPan(true);
}
setDirty();
CBofPoint NewPoint = getPosition();
CBagPanWindow *pWnd = (CBagPanWindow *)extraInfo;
const CBofRect r = pWnd->getSlideBitmap()->getCurrView();
const int mLocX = point.x + r.left - pWnd->getViewPortPos().x;
int NewXPos = mLocX;
// Constrict Dragging to width of slidebar
if (NewXPos > _slideRect.right)
NewXPos = _slideRect.right;
if (NewXPos < _slideRect.left)
NewXPos = _slideRect.left;
NewPoint.x = NewXPos;
setPosition(NewPoint);
// We need to set the state here as well as LButtonUP
// because there is a chance we won't get it
const int xIncrement = _slideRect.width() / (_numPos - 1);
const int i = (NewPoint.x - _slideRect.left) / xIncrement;
setState(i);
}
}
if (_buttonType == BTN_PUSH) {
if (getSprite() && (getSprite()->getCelCount() > 1)) {
if (!this->getRect().ptInRect(point) && _active && !_activeUp) {
_activeUp = true;
}
}
if (getSprite() && (getSprite()->getCelCount() == 1)) { // Only given down state
setVisible(false);
}
setState(0); // Set to first cel
}
return true;
}
ErrorCode CBagButtonObject::update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect, int maskColor) {
bool bDirty = false;
if (_buttonType == BTN_PUSH) {
if (getSprite() && (getSprite()->getCelCount() > 1)) {
if (_active) { // If the button is doing something
if (_activeDown) {
getSprite()->nextCel(); // Increment frame
// If this is animated, the bring it back up immediately
if (getSprite()->getCelIndex() == getSprite()->getCelCount() - 1 || getSprite()->getAnimated()) {
_activeDown = false;
}
} else if (_activeUp) { // else (going back up)
getSprite()->prevCel(); // decrement frame
// If this is animated, the let it go immediately
if (getSprite()->getCelIndex() == 0 || getSprite()->getAnimated()) {
_activeUp = false;
_active = false;
}
}
}
}
} else if (_buttonType == BTN_CHECKBOX) {
if (getSprite() && (getSprite()->getCelCount() > 1) && _active) {
if (_activeDown) {
getSprite()->nextCel(); // Increment frame
if (getSprite()->getCelIndex() == getSprite()->getCelCount() - 1) {
_active = false;
}
} else { // else (going back up)
getSprite()->prevCel(); // decrement frame
if (getSprite()->getCelIndex() == 0) {
_active = false;
}
}
}
// For checkboxes, we have to make sure that they are always
// redrawn as they will otherwise return to their state on the pan (in the
// background of the closeup).
bDirty = true;
} else if (_buttonType == BTN_HLEVER || _buttonType == BTN_VLEVER) {
if (getSprite() && (getSprite()->getCelCount() > 1)) {
if (_activeDown) {
if (getSprite()->getCelIndex() < (getSprite()->getCelCount() - 1))
getSprite()->nextCel();
_activeDown = false;
} else if (_activeUp) {
if (getSprite()->getCelIndex() > 0)
getSprite()->prevCel();
_activeUp = false;
}
setState(getSprite()->getCelIndex());
}
}
if (getSprite() && ((getSprite()->getCelCount() > 1) || isVisible())) {
const ErrorCode errorCode = CBagSpriteObject::update(bmp, pt, srcRect, maskColor);
setDirty(bDirty);
return errorCode;
}
return _errCode;
}
void CBagButtonObject::setSize(const CBofSize &size) {
if (_buttonType == BTN_SLIDER)
_slideRect = CBofRect(getPosition(), size);
CBagSpriteObject::setSize(size);
}
ParseCodes CBagButtonObject::setInfo(CBagIfstream &istr) {
bool nObjectUpdated = false;
while (!istr.eof()) {
const char ch = (char)istr.peek();
switch (ch) {
//
// +n - n number of slides in sprite
//
case '+': {
int cels;
istr.getCh();
getIntFromStream(istr, cels);
if (_buttonType == BTN_SLIDER)
_numPos = cels;
else
setCels(cels);
nObjectUpdated = true;
break;
}
// Handle a maximum framerate...
case 'F': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("FRAMERATE")) {
int nFrameRate;
istr.eatWhite();
getIntFromStream(istr, nFrameRate);
// The framerate is expressed in frames/second, so do some division
// here to store the number of milliseconds.
setFrameRate(1000 / nFrameRate);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// AS [LINK|CLOSEUP] - how to run the link
//
case 'A': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("AS")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("PUSH")) {
_buttonType = BTN_PUSH;
nObjectUpdated = true;
} else if (!sStr.find("CHECKBOX")) {
_buttonType = BTN_CHECKBOX;
nObjectUpdated = true;
} else if (!sStr.find("HLEVER")) {
_buttonType = BTN_HLEVER;
nObjectUpdated = true;
} else if (!sStr.find("VLEVER")) {
_buttonType = BTN_VLEVER;
nObjectUpdated = true;
} else if (!sStr.find("DIAL")) {
_buttonType = BTN_DIAL;
nObjectUpdated = true;
} else if (!sStr.find("SLIDER")) {
_buttonType = BTN_SLIDER;
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
putbackStringOnStream(istr, "AS ");
}
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// No match return from function
//
default: {
const ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
nObjectUpdated = true;
} else { // rc==UNKNOWN_TOKEN
if (nObjectUpdated)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
break;
}
} // end switch
} // end while
return PARSING_DONE;
}
void CBagButtonObject::setProperty(const CBofString &prop, int val) {
if (!prop.find("STATE")) {
if (getSprite()) {
if (_buttonType == BTN_CHECKBOX) {
_active = true;
if (val == 0)
_activeDown = false;
else
_activeDown = true;
if (getSprite()->getCelCount() == 1) { // Only given down state
setVisible(_activeDown);
_active = false;
}
if (val == 0)
setState(0);
else
setState(1);
} else {
if (_buttonType == BTN_SLIDER) {
CBofPoint cPos = getPosition();
cPos.x = _slideRect.left + (val * (_slideRect.width() / (_numPos - 1)));
setPosition(cPos);
setDirty(true);
}
setState(val);
getSprite()->setCel(val);
}
}
} else if (!prop.find("CURR_CEL")) {
setState(val);
if (getSprite())
getSprite()->setCel(val);
} else
CBagObject::setProperty(prop, val);
}
int CBagButtonObject::getProperty(const CBofString &prop) {
if (!prop.find("CURR_CEL")) {
if (getSprite()) {
return getSprite()->getCelIndex();
}
return 0;
}
return CBagObject::getProperty(prop);
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,126 @@
/* 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 BAGEL_BAGLIB_BUTTON_OBJECT_H
#define BAGEL_BAGLIB_BUTTON_OBJECT_H
#include "bagel/spacebar/baglib/sprite_object.h"
namespace Bagel {
namespace SpaceBar {
#define SAVE_BTN 0
#define CANCEL_BTN 1
#define RESTORE_BTN 2
#define RESTART_BTN 3
#define QUIT_BTN 4
#define LINEUP_BTN 10
#define LINEDN_BTN 11
#define PAGEUP_BTN 12
#define PAGEDN_BTN 13
/**
* CBagButtonObject is an object that can be place within the slide window.
*/
class CBagButtonObject : public CBagSpriteObject {
public:
enum BUTTON_TYPE {
BTN_PUSH = 0,
BTN_CHECKBOX = 1,
BTN_HLEVER = 2,
BTN_VLEVER = 3,
BTN_DIAL = 4,
BTN_SLIDER = 5
};
private:
bool _dragging;
CBofRect _slideRect;
int _numPos;
BUTTON_TYPE _buttonType;
bool _activeDown;
bool _activeUp;
bool _active;
CBofPoint _midPoint;
BagFuncPtr _callbackFct;
void *_callbackInfo; // Data to be passed to the function
public:
CBagButtonObject();
virtual ~CBagButtonObject();
ErrorCode attach() override;
ErrorCode detach() override;
BUTTON_TYPE getButtonType() const {
return _buttonType;
}
/**
* Takes in info and then removes the relative information and returns
* the info without the relevant info.
*/
ParseCodes setInfo(CBagIfstream &istr) override;
bool runObject() override;
// Callback function functionality - probably can be phased out
void setCallBack(BagFuncPtr func, void *funcInfo) {
_callbackFct = func;
_callbackInfo = funcInfo;
}
BagFuncPtr getCallBack() override {
return _callbackFct;
}
void *getCallBackInfo() const {
return _callbackInfo;
}
bool runCallBack() override {
if (_callbackFct) {
_callbackFct((int)getRefId(), _callbackInfo);
return true;
}
return false;
}
void onLButtonDown(uint32 /*nFlags*/, CBofPoint *point, void *) override;
void onLButtonUp(uint32 flags, CBofPoint *point, void *extraInfo) override;
bool onMouseMove(uint32 /*nFlags*/, CBofPoint point, void *extraInfo) override;
ErrorCode update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect = nullptr, int maskColor = -1) override;
void setSize(const CBofSize &size) override;
void setProperty(const CBofString &prop, int val) override;
int getProperty(const CBofString &prop) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,671 @@
/* 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/>.
*
*/
#include "common/file.h"
#include "bagel/spacebar/baglib/character_object.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/bagel.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/log.h"
namespace Bagel {
namespace SpaceBar {
CBagCharacterObject *CBagCharacterObject::_pdaWand;
bool CBagCharacterObject::_pdaAnimating;
void CBagCharacterObject::initialize() {
_pdaWand = nullptr;
_pdaAnimating = false;
}
CBagCharacterObject::CBagCharacterObject() : CBagObject() {
_xObjType = CHAR_OBJ;
_bmpBuf = nullptr;
_binBuf = nullptr;
_charTransColor = -1;
// Default is now the nullptr cursor
CBagObject::setOverCursor(0);
setTimeless(true);
_startFrame = -1;
_endFrame = -1;
_playbackSpeed = 1;
_numOfLoops = -1;
_exitAtEnd = false;
_prevFrame = -1;
_firstFrame = true;
_pAnim = false;
_saveState = false;
}
CBagCharacterObject::~CBagCharacterObject() {
CBagCharacterObject::detach();
}
ErrorCode CBagCharacterObject::attach() {
char localBuff[256];
localBuff[0] = '\0';
CBofString filename(localBuff, 256);
CBofPalette *smackPal = CBofApp::getApp()->getPalette();
filename = getFileName();
// Open the smacker file
Video::SmackerDecoder *decoder = new Video::SmackerDecoder();
decoder->setSoundType(Audio::Mixer::kSFXSoundType);
if (!decoder->loadFile(filename.getBuffer())) {
logError(buildString("char SmackOpen failed: %s ", filename.getBuffer()));
delete decoder;
return ERR_FOPEN;
}
_smacker = decoder;
// Create an offscreen bitmap to decompress smacker into
_firstFrame = true;
_bmpBuf = new CBofBitmap(_smacker->getWidth(), _smacker->getHeight(), smackPal);
if (smackPal != nullptr) {
_bmpBuf->fillRect(nullptr, smackPal->getNearestIndex(RGB(255, 255, 255)));
}
// Create the text filename
filename.makeUpper();
filename.replaceStr(".SMK", ".BIN");
if (_binBuf != nullptr) {
bofFree(_binBuf);
_binBuf = nullptr;
}
// Does file exist
if (fileExists(filename.getBuffer())) {
CBofFile cInputFile(filename.getBuffer());
_binBufLen = cInputFile.getLength();
_binBuf = (char *)bofAlloc(_binBufLen + 1);
cInputFile.read(_binBuf, _binBufLen);
}
// Set the start and stop frames if still default.
if (_playbackSpeed > 0) {
// Forward playback
if (_startFrame == -1)
_startFrame = 0;
if (_endFrame == -1) {
_endFrame = _smacker->getFrameCount();
--_endFrame;
}
} else {
// Reverse playback
if (_endFrame == -1)
_endFrame = 1;
if (_startFrame == -1)
_startFrame = _smacker->getFrameCount();
//_smacker->setReverse(true); // TODO: Not supported by SMK
}
if (_saveState) {
// Get the current state for this object
const int nState = getState();
// If the state is not the default(0) then move to the correct frame
if (nState != 0)
setFrame(nState);
}
if (_numOfLoops != 0) {
_smacker->start();
} else {
_smacker->stop();
}
setVisible(true);
updatePosition();
refreshCurrentFrame();
// Get chroma from main app now
_charTransColor = CBagel::getBagApp()->getChromaColor();
return CBagObject::attach();
}
ErrorCode CBagCharacterObject::detach() {
if (_saveState) {
// Save off the state/frame information as we detach
// so that we can recreate the scene when we attach again
if (_smacker != nullptr) {
setState(_smacker->getCurFrame());
}
} else {
// Decrement current loop from happening again
if (_numOfLoops > 0)
_numOfLoops--;
}
if (_smacker != nullptr) {
_smacker->close();
delete _smacker;
_smacker = nullptr;
}
delete _bmpBuf;
_bmpBuf = nullptr;
if (_binBuf != nullptr) {
bofFree(_binBuf);
_binBuf = nullptr;
}
if (this == _pdaWand) {
_pdaWand = nullptr;
}
return CBagObject::detach();
}
bool CBagCharacterObject::refreshCurrentFrame() {
bool newFrameFl = true;
if (_bmpBuf != nullptr) {
if (_smacker != nullptr) {
// Decode the next frame
const Graphics::Surface *surf = _smacker->decodeNextFrame();
if (surf) {
Graphics::ManagedSurface &destSurf = *_bmpBuf;
// Copy the decoded frame into the offscreen bitmap
destSurf.setPalette(_smacker->getPalette(), 0, 256);
destSurf.blitFrom(*surf);
} else {
newFrameFl = false;
}
} else {
// Return false so we don't update our position
newFrameFl = false;
}
}
return newFrameFl;
}
CBofRect CBagCharacterObject::getRect() {
const CBofPoint pos = getPosition();
CBofSize size;
if (_bmpBuf)
size = _bmpBuf->getSize();
return CBofRect(pos, size);
}
void CBagCharacterObject::updatePosition() {
// We have an input file
if (_binBuf != nullptr && _smacker != nullptr) {
// Seek to correct place in the file
int frame = _smacker->getCurFrame();
if (frame < 0)
frame = 0;
int32 lSeekPos = frame * 2 * sizeof(int32);
// Read from our memory buffer rather than going to
// disk for the position of the smack dudes.
// Check that we are going to fit
if (lSeekPos + (int32)(2 * sizeof(int32)) <= _binBufLen) {
const int xPos = READ_LE_INT32(&_binBuf[lSeekPos]);
lSeekPos += sizeof(int32);
const int yPos = READ_LE_INT32(&_binBuf[lSeekPos]);
// A valid number was read
if ((xPos > -1) && (yPos > -1)) {
const CBofPoint newPos(xPos, yPos);
setPosition(newPos);
}
}
}
}
bool CBagCharacterObject::doAdvance() {
// Assume we're not advancing
bool doAdvanceFl = false;
const bool pdaWandFl = (this == _pdaWand);
if (pdaWandFl) {
_pdaAnimating = false;
}
// If we are done looping just return with false
if (!_numOfLoops)
return false;
// If we got a background bitmap
if (_bmpBuf != nullptr) {
// If This Panimation is modal, or Panimations are ON, then get next frame.
if (isModal() || !_pAnim || CBagMasterWin::getPanimations()) {
if (_smacker->needsUpdate()) {
doAdvanceFl = true;
// Paint the current frame to the BMP
if (refreshCurrentFrame()) {
_smacker->resetStartTime();
// Get the current frame in the correct place
updatePosition();
}
if (_playbackSpeed > 0) {
// We've looped
if (_smacker->getCurFrame() == _endFrame) {
if (_numOfLoops > 0)
_numOfLoops--; // decrement num of loops
// Get next frame, will loop to beginning
_smacker->rewind();
_smacker->start();
}
} else {
if (_smacker->getCurFrame() == _endFrame || _smacker->getCurFrame() == 1) {
if (_numOfLoops > 0)
_numOfLoops--; // decrement num of loops
// Get next frame, will loop to beginning
setFrame(_startFrame);
} else {
setFrame(_smacker->getCurFrame() - 1); // HACK: Reverse playback
}
}
}
} else if (_firstFrame) {
// Only play the first frame
_firstFrame = false;
// Get the current frame in the correct place
updatePosition();
// Paint the current frame to the BMP
refreshCurrentFrame();
}
}
// We got a Bitmap
if (pdaWandFl) {
_pdaAnimating = doAdvanceFl;
}
return doAdvanceFl;
}
bool CBagCharacterObject::isInside(const CBofPoint &point) {
if (getRect().ptInRect(point) && _charTransColor >= 0) {
if (_bmpBuf) {
const int x = point.x - getRect().left;
const int y = point.y - getRect().top;
const int color = _bmpBuf->readPixel(x, y);
return (color != _charTransColor);
}
return true;
}
return false;
}
bool CBagCharacterObject::runObject() {
CBagObject::runObject();
return false;
}
ErrorCode CBagCharacterObject::update(CBofBitmap *bmp, CBofPoint pt, CBofRect * /*srcRect, unused*/, int /*maskColor, unused*/) {
// Get the original position for character
const CBofPoint originalPos = getPosition();
const bool doAdvanceFl = doAdvance();
// If we have more frames advance this, else exit and detach if needed
if (!doAdvanceFl && _exitAtEnd) {
// Run the ending objects
detach();
}
if (_bmpBuf) {
// Get the new position for the character
const CBofPoint newPos = getPosition();
// Get access to the current sDev
// Paint in the new pos
return _bmpBuf->paint(bmp, (pt.x + (newPos.x - originalPos.x)), (pt.y + (newPos.y - originalPos.y)), nullptr, _charTransColor);
}
return ERR_NONE;
}
ParseCodes CBagCharacterObject::setInfo(CBagIfstream &istr) {
bool objectUpdatedFl = false;
while (!istr.eof()) {
const char ch = (char)istr.peek();
switch (ch) {
// SAVESTATE - Maintain the state of the character
case 'K': {
char localStr[256];
localStr[0] = 0;
CBofString str(localStr, 256);
getAlphaNumFromStream(istr, str);
if (!str.find("KEEPSTATE")) {
istr.eatWhite();
_saveState = true;
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, str);
}
break;
}
// LOOP n - n number of times to loop (-1 infinate)
case 'L': {
char localStr[256];
localStr[0] = 0;
CBofString str(localStr, 256);
getAlphaNumFromStream(istr, str);
if (!str.find("LOOP")) {
istr.eatWhite();
getIntFromStream(istr, _numOfLoops);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, str);
}
break;
}
// SPEED n - n pace of playback (negative is backward), (0 to hold at current frame)
case 'S': {
char localStr[256];
localStr[0] = 0;
CBofString str(localStr, 256);
getAlphaNumFromStream(istr, str);
if (!str.find("SPEED")) {
istr.eatWhite();
getIntFromStream(istr, _playbackSpeed);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, str);
}
break;
}
// EXITATEND - detach at end of looping (call run after objects)
case 'E': {
char localStr[256];
localStr[0] = 0;
CBofString str(localStr, 256);
getAlphaNumFromStream(istr, str);
if (!str.find("EXITATEND")) {
istr.eatWhite();
_exitAtEnd = true;
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, str);
}
break;
}
// PANIM - Specifies if this object should be affected by the user
// option Panimations On/Off
case 'P': {
CBofString str;
getAlphaNumFromStream(istr, str);
if (!str.find("PANIM")) {
istr.eatWhite();
_pAnim = true;
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, str);
}
break;
}
// FRAME [start, end]- start and end frames of the move
case 'F': {
char localStr[256];
localStr[0] = 0;
CBofString str(localStr, 256);
getAlphaNumFromStream(istr, str);
if (!str.find("FRAME")) {
CBofRect r;
istr.eatWhite();
getRectFromStream(istr, r);
_startFrame = r.left;
_endFrame = r.top;
if (r.width() && r.height()) {
// error of some type
}
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, str);
}
break;
}
// No match return from function
default: {
const ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
objectUpdatedFl = true;
} else { // rc==UNKNOWN_TOKEN
if (objectUpdatedFl)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
break;
}
}
}
return PARSING_DONE;
}
void CBagCharacterObject::arrangeFrames() {
const int start = getStartFrame();
const int end = getEndFrame();
if (_playbackSpeed < 0) {
_startFrame = MAX(start, end);
_endFrame = MIN(start, end);
} else {
_startFrame = MIN(start, end);
_endFrame = MAX(start, end);
}
}
void CBagCharacterObject::setNumOfLoops(int n) {
_numOfLoops = n;
if (_smacker != nullptr) {
if (_numOfLoops != 0) {
_smacker->start();
} else {
_smacker->stop();
}
}
// If this character is modal run until done looping
if (isModal() && isAttached()) {
CBagStorageDevWnd *win = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if (win != nullptr) {
win->runModal(this);
}
}
}
void CBagCharacterObject::setPlaybackSpeed(int n) {
if (_playbackSpeed != n) {
if (n < 0) {
_startFrame++;
_endFrame++;
} else {
_startFrame--;
_endFrame--;
}
_playbackSpeed = n;
arrangeFrames();
int frame = getStartFrame();
if (n < 0 && frame == (int)_smacker->getFrameCount()) {
frame--; // HACK: Reverse rewind
}
setCurrentFrame(frame);
}
}
void CBagCharacterObject::setStartFrame(int n) {
arrangeFrames();
_startFrame = n;
arrangeFrames();
}
void CBagCharacterObject::setEndFrame(int n) {
arrangeFrames();
_endFrame = n;
arrangeFrames();
}
void CBagCharacterObject::setCurrentFrame(int n) {
// Make sure that it is within specified values?
//
// Due to some distinctly bogus code that manipulates the
// start and end frame, the current frame passed in can be negative, which
// will cause slacker-smacker to go toes up, handle that here.
setFrame(n);
// Added updatePosition() because if any movies go backwards, and use
// a .BIN file, then it would not have worked.
updatePosition();
//refreshCurrentFrame();
}
void CBagCharacterObject::setFrame(int n) {
// Make sure that it is within specified values?
if (_smacker != nullptr) {
n--;
n = CLIP<int>(n, 0, _smacker->getFrameCount() - 1);
const Graphics::Surface *surf = _smacker->forceSeekToFrame(n);
if (surf) {
Graphics::ManagedSurface &destSurf = *_bmpBuf;
// Copy the decoded frame into the offscreen bitmap
destSurf.setPalette(_smacker->getPalette(), 0, 256);
destSurf.blitFrom(*surf);
}
}
}
void CBagCharacterObject::setProperty(const CBofString &prop, int val) {
if (!prop.find("LOOP"))
setNumOfLoops(val);
else if (!prop.find("SPEED"))
setPlaybackSpeed(val);
else if (!prop.find("START_FRAME"))
setStartFrame(val);
else if (!prop.find("END_FRAME"))
setEndFrame(val);
else if (!prop.find("CURR_FRAME")) // This one will not work currently
setCurrentFrame(val);
else
CBagObject::setProperty(prop, val);
}
int CBagCharacterObject::getProperty(const CBofString &prop) {
if (!prop.find("LOOP"))
return getNumberOfLoops();
if (!prop.find("SPEED"))
return getPlaybackSpeed();
if (!prop.find("START_FRAME"))
return getStartFrame();
if (!prop.find("END_FRAME"))
return getEndFrame();
if (!prop.find("CURR_FRAME")) // This one will not work currently
return getCurrentFrame();
return CBagObject::getProperty(prop);
}
void CBagCharacterObject::setPdaWand(CBagCharacterObject *pdaWand) {
_pdaWand = pdaWand;
}
bool CBagCharacterObject::pdaWandAnimating() {
if (_pdaWand == nullptr || !_pdaWand->isAttached()) {
CBagStorageDev *pda = g_SDevManager->getStorageDevice("BPDA_WLD");
if (pda != nullptr) {
CBagCharacterObject *wand = (CBagCharacterObject *)pda->getObject("WANDANIM");
if (wand != nullptr) {
CBagCharacterObject::setPdaWand(wand);
}
}
}
return _pdaAnimating;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,130 @@
/* 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 BAGEL_BAGLIB_BAG_CHARACTER_OBJECT_H
#define BAGEL_BAGLIB_BAG_CHARACTER_OBJECT_H
#include "video/smk_decoder.h"
#include "bagel/spacebar/baglib/object.h"
namespace Bagel {
namespace SpaceBar {
class CBagCharacterObject : public CBagObject {
protected:
Video::SmackerDecoder *_smacker = nullptr;
CBofBitmap *_bmpBuf = nullptr;
int _charTransColor = 0;
char *_binBuf = nullptr;
int32 _binBufLen = 0;
int _playbackSpeed = 0;
int _numOfLoops = 0;
int _startFrame = 0;
int _endFrame = 0;
bool _exitAtEnd : 1;
bool _firstFrame : 1;
bool _saveState : 1; // Flag to save the state/frame of the character
bool _pAnim : 1; // If affected by Panimations On/Off setting
int _prevFrame = 0;
void setFrame(int n);
// Keep track of the PDA wand and the number of frames it has
static CBagCharacterObject *_pdaWand;
static bool _pdaAnimating;
public:
CBagCharacterObject();
virtual ~CBagCharacterObject();
static void initialize();
// Return ERR_NONE if the Object had members that are properly initialized/de-initialized
ErrorCode attach() override;
ErrorCode detach() override;
CBofRect getRect() override;
ErrorCode update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect = nullptr, int maskColor = -1) override;
bool doAdvance();
void updatePosition();
bool refreshCurrentFrame();
bool runObject() override;
bool isInside(const CBofPoint &point) override;
void arrangeFrames();
int getNumberOfLoops() const {
return _numOfLoops;
}
int getPlaybackSpeed() const {
return _playbackSpeed;
}
int getStartFrame() const {
return _startFrame;
}
int getEndFrame() const {
return _endFrame;
}
int getCurrentFrame() const {
return (_smacker != nullptr) ? _smacker->getCurFrame() : -1;
}
bool isModalDone() override {
return !_numOfLoops;
}
bool isPanim() const {
return _pAnim;
}
void setNumOfLoops(int n);
void setPlaybackSpeed(int n);
void setStartFrame(int n);
void setEndFrame(int n);
void setCurrentFrame(int n);
ParseCodes setInfo(CBagIfstream &istr) override;
void setProperty(const CBofString &prop, int val) override;
int getProperty(const CBofString &prop) override;
// Remember the pda wand, we'll need to know about it and
// it's total number of frames.
static void setPdaWand(CBagCharacterObject *pdaWand);
static bool pdaWandAnimating();
bool isStationary() const {
return _binBuf != nullptr;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,79 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/chat_wnd.h"
#include "bagel/spacebar/baglib/text_object.h"
namespace Bagel {
namespace SpaceBar {
CBagChatWnd::CBagChatWnd() : CBagStorageDevWnd() {
}
ErrorCode CBagChatWnd::attach() {
assert(isValidObject(this));
if (CBagStorageDevWnd::attach() == ERR_NONE) {
show();
invalidateRect(nullptr);
updateWindow();
}
return _errCode;
}
void CBagChatWnd::onTimer(uint32 /*nTimerId*/) {
assert(isValidObject(this));
}
void CBagChatWnd::onMouseMove(uint32 flags, CBofPoint *pos, void *) {
assert(isValidObject(this));
assert(pos != nullptr);
// Use default behavior 1st
CBagStorageDevWnd::onMouseMove(flags, pos);
// If over a chat choice, then highlight it
CBofList<CBagObject *> *bagObjectList = getObjectList();
// Run through background object list and find if the cursor is over an object
if (bagObjectList != nullptr) {
// Go through list backwards to find the 1st top-most object
CBofListNode<CBagObject *> *currNode = bagObjectList->getTail();
while (currNode != nullptr) {
CBagObject *currNodeItem = currNode->getNodeItem();
if (currNodeItem->getType() == TEXT_OBJ) {
((CBagTextObject *)currNodeItem)->setColor(4);
currNodeItem->setDirty(true);
if (currNodeItem->isAttached() && currNodeItem->isInside(*pos)) {
((CBagTextObject *)currNodeItem)->setColor(8);
}
}
currNode = currNode->_pPrev;
}
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,47 @@
/* 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 BAGEL_BAGLIB_CHAT_WND_H
#define BAGEL_BAGLIB_CHAT_WND_H
#include "bagel/spacebar/baglib/storage_dev_win.h"
namespace Bagel {
namespace SpaceBar {
class CBagChatWnd : public CBagStorageDevWnd {
public:
CBagChatWnd();
/**
* Called to overload new set backgrounds. Calls the set backdrop pure
* virtual function by default.
*/
ErrorCode attach() override;
void onTimer(uint32 timerId) override;
void onMouseMove(uint32 flags, CBofPoint *pos, void * = nullptr) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,493 @@
/* 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/>.
*
*/
#include "gui/debugger.h"
#include "bagel/spacebar/baglib/command_object.h"
#include "bagel/spacebar/baglib/dossier_object.h"
#include "bagel/spacebar/baglib/rp_object.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/boflib/gui/movie.h"
#include "bagel/spacebar/baglib/dev_dlg.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/boflib/sound.h"
#include "bagel/bagel.h"
#include "bagel/boflib/file_functions.h"
namespace Bagel {
namespace SpaceBar {
extern bool g_restoreObjectListFl;
extern bool g_allowattachActiveObjectsFl;
CBagCommandObject::CBagCommandObject() {
_xObjType = COMMAND_OBJ;
setVisible(false);
setTimeless(true);
}
bool CBagCommandObject::runObject() {
static int iteration = 0;
bool rc = false;
// Don't allow more than 10 (recursively)
if (iteration < 10) {
iteration++;
CBofString srcSDev = _srcSDev;
CBofString dstSDev = _destSDev;
// Check if these items should be replaced by the current sdev
if (!srcSDev.isEmpty() && !srcSDev.find(CURRSDEV_TOKEN)) {
srcSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()->getName();
}
if (!dstSDev.isEmpty() && !dstSDev.find(CURRSDEV_TOKEN)) {
dstSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()->getName();
}
// Check if these items should be replaced by the previous sdev
if (!srcSDev.isEmpty() && !srcSDev.find(PREVSDEV_TOKEN)) {
srcSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()->getPrevSDev();
}
if (!dstSDev.isEmpty() && !dstSDev.find(PREVSDEV_TOKEN)) {
dstSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()->getPrevSDev();
}
if (getFileName() == "REMOVE") {
static bool removeFl = false;
if (!removeFl) {
removeFl = true;
if (!_objName.isEmpty() && !srcSDev.isEmpty()) {
g_SDevManager->removeObject(srcSDev, _objName);
}
removeFl = false;
}
} else if (getFileName() == "INSERT2") {
if (!_objName.isEmpty() && !dstSDev.isEmpty()) {
g_allowattachActiveObjectsFl = false;
g_SDevManager->addObject(dstSDev, _objName);
g_allowattachActiveObjectsFl = true;
}
} else if (getFileName() == "INSERT") {
if (!_objName.isEmpty() && !dstSDev.isEmpty()) {
g_SDevManager->addObject(dstSDev, _objName);
}
} else if (getFileName() == "TRANSFER") {
if (!_objName.isEmpty() && !srcSDev.isEmpty() && !dstSDev.isEmpty()) {
g_SDevManager->moveObject(dstSDev, srcSDev, _objName);
}
} else if (getFileName().find("FLUSHQUEUE") == 0) {
char buffer[20];
int slot;
slot = 0;
Common::strcpy_s(buffer, getFileName());
if (strlen(buffer) == 11) {
slot = buffer[10] - 48;
}
assert(slot >= 0 && slot < 8);
} else if (getFileName() == "CLOSE") {
CBagStorageDevWnd *currentSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
currentSDev->close();
} else if (getFileName() == "UPDATE") {
static bool updateFl = false;
if (!updateFl) {
updateFl = true;
CBagStorageDevWnd *currentSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
currentSDev->attachActiveObjects();
updateFl = false;
}
} else if (getFileName() == "EVENTLOOP") {
static bool eventLoopFl = false;
// prevent recursion
//
if (!eventLoopFl) {
eventLoopFl = true;
CBagStorageDev *currSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if (currSDev != nullptr) {
if (currSDev->getDeviceType() == SDEV_GAMEWIN) {
CBagPanWindow *panWin = (CBagPanWindow *)currSDev;
panWin->onTimer(EVAL_EXPR);
}
}
eventLoopFl = false;
}
} else if (getFileName() == "STOPPAINT") {
g_allowPaintFl = false;
} else if (getFileName() == "REMOVEWIELD") {
// Remove currently wielded object from the game
if (CBagPanWindow::_pWieldBmp != nullptr) {
CBagObject *currObj = CBagPanWindow::_pWieldBmp->getCurrObj();
if (currObj != nullptr) {
g_SDevManager->removeObject(CBagPanWindow::_pWieldBmp->getName(), currObj->getRefName());
}
}
} else if (getFileName() == "PAINT") {
// Get a pointer to the current game window
CBagStorageDevWnd *gameWin = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if (gameWin != nullptr) {
gameWin->paintScreen(nullptr);
}
} else if (getFileName() == "STOPWAVE") {
CBofSound::stopWaveSounds();
} else if (getFileName() == "STASHWIELD") {
// Stash the currently wielded item
if (CBagPanWindow::_pWieldBmp != nullptr) {
CBagObject *currObj = CBagPanWindow::_pWieldBmp->getCurrObj();
if (currObj != nullptr) {
g_SDevManager->moveObject("INV_WLD", CBagPanWindow::_pWieldBmp->getName(), currObj->getRefName());
CBagPanWindow::_pWieldBmp->setCurrObj(nullptr);
}
}
} else if (getFileName() == "DEATH") {
CBagel::getBagApp()->getMasterWnd()->postUserMessage(WM_DIE, 0);
g_allowPaintFl = false;
} else if (getFileName() == "GOPAINT") {
g_allowPaintFl = true;
} else if (getFileName() == "DEACTIVATEPDA") {
// Get a pointer to the current game window
CBagStorageDevWnd *gameWin = (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev());
// Pull down the PDA (if it exists)
if (gameWin->getDeviceType() == SDEV_GAMEWIN) {
((CBagPanWindow *)gameWin)->deactivatePDA();
((CBagPanWindow *)gameWin)->waitForPDA();
}
} else if (getFileName() == "ROTATETOFLY") {
if (CBagMasterWin::getFlyThru()) {
CBagMasterWin::setActiveCursor(6);
CBagStorageDev *currSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if ((currSDev != nullptr) && (currSDev->getDeviceType() == SDEV_GAMEWIN)) {
CBagPanWindow *currWin = (CBagPanWindow *)currSDev;
CBofPoint loc = getPosition();
currWin->rotateTo(loc);
}
}
} else if (getFileName() == "ROTATETO") {
CBagMasterWin::setActiveCursor(6);
CBagStorageDev *currSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if ((currSDev != nullptr) && (currSDev->getDeviceType() == SDEV_GAMEWIN)) {
CBagPanWindow *currWin = (CBagPanWindow *)currSDev;
CBofPoint loc = getPosition();
currWin->rotateTo(loc);
}
} else if (getFileName() == "SETQVOL") {
CBofSound::setQVol(getPosition().x, getPosition().y);
} else if (getFileName() == "TURN") {
// Cause 1 turn to go by
g_VarManager->incrementTimers();
} else if (getFileName() == "RP_UPDATE_QUEUE") {
// Execute any waiting residue printing results.
CBagRPObject::updateResiduePrintedQueue();
} else if (getFileName() == "RP_RUN_QUEUE") {
// Execute any waiting residue printing results.
CBagRPObject::runResiduePrintedQueue();
} else if (getFileName() == "RP_DEACTIVATE_RESULTS") {
// Execute any waiting residue printing results.
CBagRPObject::deactivateResiduePrintedQueue();
} else if (getFileName() == "RP_DEACTIVATE_REVIEW") {
// Execute any waiting residue printing results.
CBagRPObject::deactivateResiduePrintedReview();
} else if (getFileName() == "RP_DEACTIVATE_DOSSIER") {
// Execute any waiting residue printing results.
CBagDossierObject::deactivateCurDossier();
} else if (getFileName() == "RP_ACTIVATE_REVIEW") {
// Execute any waiting residue printing results.
CBagRPObject::activateResiduePrintedReview();
} else if (getFileName() == "SAVESTACK") {
CBagMasterWin *pWin = CBagel::getBagApp()->getMasterWnd();
if (pWin != nullptr) {
pWin->saveSDevStack();
}
} else if (getFileName() == "DEATH2") {
CBagel::getBagApp()->getMasterWnd()->postUserMessage(WM_DIE, 2);
g_allowPaintFl = false;
} else if (getFileName() == "ENTRYTHUD") { // Thud
CBofRect tmpRect(60, 50, 137, 70);
CBofString bmpName("$SBARDIR\\GENERAL\\POPUP\\THUDPOP.BMP");
fixPathName(bmpName);
CDevDlg dlg;
dlg.createWindow(bmpName, CBagel::getBagApp()->getMasterWnd(), CBofApp::getApp()->getPalette(), &tmpRect, false);
dlg.doModal();
dlg.destroy();
} else if (getFileName() == "ENTRYFLEE") { // Fleebix
CBofRect tmpRect(35, 48, 114, 69);
CBofString bmpName("$SBARDIR\\GENERAL\\POPUP\\FLEEDAT.BMP");
fixPathName(bmpName);
CDevDlg dlg;
dlg.createWindow(bmpName, CBagel::getBagApp()->getMasterWnd(), CBofApp::getApp()->getPalette(), &tmpRect, false);
dlg.doModal();
dlg.destroy();
} else if (getFileName() == "ENTRYCLICK") { // Click's locker combo
CBofRect tmpRect(60, 49, 138, 68);
CBofString bmpName("$SBARDIR\\GENERAL\\POPUP\\CLICKPOP.BMP");
fixPathName(bmpName);
CDevDlg dlg;
dlg.createWindow(bmpName, CBagel::getBagApp()->getMasterWnd(), CBofApp::getApp()->getPalette(), &tmpRect, false);
dlg.doModal();
dlg.destroy();
} else if (getFileName() == "ENTRYFRUIT") { // MegaWave the fruit
CBofRect tmpRect(35, 49, 114, 68);
CBofString bmpName("$SBARDIR\\GENERAL\\POPUP\\CLICKDAT.BMP");
fixPathName(bmpName);
CDevDlg dlg;
dlg.createWindow(bmpName, CBagel::getBagApp()->getMasterWnd(), CBofApp::getApp()->getPalette(), &tmpRect, false);
dlg.doModal();
dlg.destroy();
} else if (getFileName() == "D7CODE1DLG") { // Deven-7 code word
CBofRect tmpRect(10, 48, 189, 69);
CBofString bmpName("$SBARDIR\\GENERAL\\POPUP\\DEVENPOP.BMP");
fixPathName(bmpName);
CDevDlg dlg;
dlg.createWindow(bmpName, CBagel::getBagApp()->getMasterWnd(), CBofApp::getApp()->getPalette(), &tmpRect, true);
dlg.doModal();
dlg.destroy();
} else if (getFileName() == "SNAPTO") {
CBagStorageDev *currSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if ((currSDev != nullptr) && (currSDev->getDeviceType() == SDEV_GAMEWIN)) {
CBagPanWindow *currWin = (CBagPanWindow *)currSDev;
if (currWin->getSlideBitmap() != nullptr) {
int x = getPosition().x;
int y = getPosition().y;
CBofRect cRect;
cRect.setRect(x, y, x + 480 - 1, y + 360 - 1);
currWin->getSlideBitmap()->setCurrView(cRect);
}
}
} else if (getFileName() == "RESUMESOUND") {
CBofSound::resumeSounds();
} else if (getFileName() == "PAUSESOUND") {
CBofSound::pauseSounds();
} else if (getFileName() == "STOPMIDI") {
CBofSound::stopMidiSounds();
} else if (getFileName() == "WAITWAVE") {
CBofSound::waitWaveSounds();
} else if (getFileName() == "WAITMIDI") {
CBofSound::waitMidiSounds();
} else if (getFileName() == "ACTIVATEPDA") {
// Get a pointer to the current game window
CBagStorageDevWnd *mainWin = (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev());
// Pull up the PDA (if it exists)
//
if (mainWin->getDeviceType() == SDEV_GAMEWIN) {
((CBagPanWindow *)mainWin)->activatePDA();
((CBagPanWindow *)mainWin)->waitForPDA();
}
} else if (getFileName() == "SHOWPDALOG") {
// Get a pointer to the current game window
CBagPDA *pda = (CBagPDA *)g_SDevManager->getStorageDevice("BPDA_WLD");
if (pda) {
pda->showLog();
}
} else if (getFileName() == "OBJLIST") {
g_restoreObjectListFl = false;
} else if (getFileName() == "WIN") {
CBagMasterWin *mainWin = CBagel::getBagApp()->getMasterWnd();
if (mainWin != nullptr) {
CBofBitmap bmp(640, 480, CBofApp::getApp()->getPalette());
bmp.fillRect(nullptr, COLOR_BLACK);
bmp.paint(mainWin, 0, 0);
g_allowPaintFl = false;
CBofString smkName("$SBARDIR\\BAR\\EVGAMWIN.SMK");
fixPathName(smkName);
// Play the movie only if it exists
if (fileExists(smkName.getBuffer())) {
bofPlayMovie(mainWin, smkName.getBuffer());
bmp.paint(mainWin, 0, 0);
}
// Display Credits
mainWin->showCreditsDialog(mainWin);
// Exit the game
CBagel::getBagApp()->getMasterWnd()->close();
}
g_engine->quitGame();
} else if (getFileName() == "BREAK") {
// As far as I'm aware, this can't actually happen in the game,
// but what the heck, ScummVM has a console, let's hook it up
g_engine->getDebugger()->attach();
} else {
reportError(ERR_UNKNOWN, "Invalid RUN COMMAND = %s", (const char *)getFileName());
}
rc = CBagObject::runObject();
iteration--;
}
return rc;
}
ParseCodes CBagCommandObject::setInfo(CBagIfstream &istr) {
bool objectUpdatedFl = false;
while (!istr.eof()) {
istr.eatWhite();
const char ch = (char)istr.peek();
switch (ch) {
//
// OBJECT
//
case 'O': {
char localBuffer[256];
localBuffer[0] = 0;
CBofString curStr(localBuffer, 256);
getAlphaNumFromStream(istr, curStr);
if (!curStr.find("OBJECT")) {
istr.eatWhite();
getAlphaNumFromStream(istr, _objName);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, curStr);
}
break;
}
//
// FROM
//
case 'F': {
char localBuffer[256];
localBuffer[0] = 0;
CBofString curStr(localBuffer, 256);
getAlphaNumFromStream(istr, curStr);
if (!curStr.find("FROM")) {
istr.eatWhite();
getAlphaNumFromStream(istr, _srcSDev);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, curStr);
}
break;
}
//
// TO
//
case 'T': {
char localBuffer[256];
localBuffer[0] = 0;
CBofString curStr(localBuffer, 256);
getAlphaNumFromStream(istr, curStr);
if (!curStr.find("TO")) {
istr.eatWhite();
getAlphaNumFromStream(istr, _destSDev);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, curStr);
}
break;
}
//
// No match return from function
//
default: {
const ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
objectUpdatedFl = true;
} else { // rc==UNKNOWN_TOKEN
if (objectUpdatedFl)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
break;
}
}
}
return PARSING_DONE;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,55 @@
/* 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 BAGEL_BAGLIB_BAG_COMMAND_OBJECT_H
#define BAGEL_BAGLIB_BAG_COMMAND_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagCommandObject transfers objects from one location to another
*/
class CBagCommandObject : public CBagObject {
private:
CBofString _objName;
CBofString _srcSDev;
CBofString _destSDev;
public:
CBagCommandObject();
/**
* Takes in info and then removes the relative information
* and returns the info without the relevant info.
*/
ParseCodes setInfo(CBagIfstream &istr) override;
bool runObject() override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,140 @@
/* 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/>.
*
*/
#include "graphics/cursorman.h"
#include "bagel/spacebar/baglib/cursor.h"
#include "bagel/boflib/cursor_data.h"
namespace Bagel {
namespace SpaceBar {
CBagCursor *CBagCursor::_currentCursor;
CSystemCursor *CBagCursor::_systemCursor;
void CBagCursor::initialize() {
_currentCursor = nullptr;
_systemCursor = new CSystemCursor();
}
void CBagCursor::shutdown() {
delete _systemCursor;
}
void CBagCursor::showSystemCursor() {
_systemCursor->setCurrent();
}
CBagCursor::CBagCursor() {
_bitmap = nullptr;
_x = 0;
_y = 0;
_sharedPalFl = false;
// Default is that this is not a wielded cursor
setWieldCursor(false);
}
CBagCursor::CBagCursor(CBofBitmap *bmp) {
_bitmap = nullptr;
_x = 0;
_y = 0;
_sharedPalFl = false;
load(bmp);
// Default is that this is not a wielded cursor
setWieldCursor(false);
}
CBagCursor::CBagCursor(const char *fileName, bool sharedPalFl) {
assert(fileName != nullptr);
_bitmap = nullptr;
_x = 0;
_y = 0;
_sharedPalFl = sharedPalFl;
strncpy(_fileName, fileName, MAX_FNAME - 1);
// Default is that this is not a wielded cursor
setWieldCursor(false);
}
CBagCursor::~CBagCursor() {
assert(isValidObject(this));
unLoad();
}
void CBagCursor::setHotspot(int x, int y) {
_x = x;
_y = y;
}
CBofPoint CBagCursor::getHotspot() const {
return CBofPoint(_x, _y);
}
ErrorCode CBagCursor::load(CBofBitmap *bmp) {
assert(isValidObject(this));
assert(bmp != nullptr);
unLoad();
_bitmap = bmp;
return _errCode;
}
ErrorCode CBagCursor::load(const char *fileName, CBofPalette *pal) {
assert(isValidObject(this));
assert(fileName != nullptr);
unLoad();
_bitmap = loadBitmap(fileName, pal, _sharedPalFl);
return _errCode;
}
void CBagCursor::unLoad() {
assert(isValidObject(this));
delete _bitmap;
_bitmap = nullptr;
}
void CBagCursor::setCurrent() {
_currentCursor = this;
CursorMan.replaceCursorPalette(_bitmap->getPalette()->getData(), 0, Graphics::PALETTE_COUNT);
CursorMan.replaceCursor(_bitmap->getSurface(), _x, _y, 1);
}
void CSystemCursor::setCurrent() {
_currentCursor = this;
Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
CursorMan.replaceCursorPalette(CURSOR_PALETTE, 0, ARRAYSIZE(CURSOR_PALETTE) / 3);
CursorMan.replaceCursor(ARROW_CURSOR, CURSOR_W, CURSOR_H, 0, 0, 0, true, &format);
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,131 @@
/* 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 BAGEL_BAGLIB_CURSOR_H
#define BAGEL_BAGLIB_CURSOR_H
#include "bagel/spacebar/boflib/gfx/bitmap.h"
#include "bagel/boflib/error.h"
namespace Bagel {
namespace SpaceBar {
class CSystemCursor;
class CBagCursor : public CBofObject, public CBofError {
private:
char _fileName[MAX_FNAME];
CBofBitmap *_bitmap;
int _x;
int _y;
bool _sharedPalFl;
bool _wieldCursorFl;
protected:
static CBagCursor *_currentCursor;
static CSystemCursor *_systemCursor;
public:
CBagCursor();
CBagCursor(CBofBitmap *bmp);
CBagCursor(const char *fileName, bool sharedPalFl = false);
static void initialize();
static void shutdown();
static void showSystemCursor();
static void hideSystemCursor() {
_currentCursor = nullptr;
}
~CBagCursor();
void setHotspot(int x, int y);
CBofPoint getHotspot() const;
int getX() const {
return _x;
}
int getY() const {
return _y;
}
ErrorCode load() {
return load(_fileName);
}
ErrorCode load(CBofBitmap *bmp);
ErrorCode load(const char *fileName, CBofPalette *pal = nullptr);
void unLoad();
CBofBitmap *getImage() const {
return _bitmap;
}
ErrorCode setImage(CBofBitmap *bmp) {
return load(bmp);
}
static CBagCursor *getCurrent() {
return _currentCursor;
}
static bool isSystemCursorVisible() {
return _currentCursor && _currentCursor->isSystemCursor();
}
/**
* Flag whether this is a wielded cursor or not
*/
void setWieldCursor(bool b) {
_wieldCursorFl = b;
}
bool IsWieldCursor() const {
return _wieldCursorFl;
}
void show() {
setCurrent();
}
void hide() {
_currentCursor = nullptr;
}
virtual void setCurrent();
virtual bool isSystemCursor() const {
return false;
}
};
class CSystemCursor : public CBagCursor {
public:
CSystemCursor() : CBagCursor() {
}
void setCurrent() override;
bool isSystemCursor() const override {
return true;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,196 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/dev_dlg.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/boflib/std_keys.h"
namespace Bagel {
namespace SpaceBar {
#define MENU_DFLT_HEIGHT 20
CDevDlg::CDevDlg(int nButtonX, int buttonY) {
_titleText = nullptr;
_guessText = nullptr;
_buttonX = nButtonX;
_buttonY = buttonY;
_achGuess[0] = '\0';
_guessCount = 0;
_useExtraFl = false;
}
CDevDlg::~CDevDlg() {
delete _titleText;
_titleText = nullptr;
}
ErrorCode CDevDlg::createWindow(const char *bmp, CBofWindow *wnd, CBofPalette *pal, CBofRect *rect, bool useExtraFl) {
assert(isValidObject(this));
assert(bmp != nullptr);
assert(wnd != nullptr);
assert(pal != nullptr);
assert(rect != nullptr);
_useExtraFl = useExtraFl;
_guessText = new CBofText();
_guessText->setupText(rect, JUSTIFY_LEFT);
_guessCount = 0;
Common::fill(_achGuess, _achGuess + ACH_GUESS_MAX_CHARS, 0);
CBofBitmap *bitmap = nullptr;
if (bmp != nullptr)
bitmap = new CBofBitmap(bmp, pal);
// Fall back to original dialog on failure
if (bitmap == nullptr) {
bitmap = new CBofBitmap(200, 100, pal);
assert(pal != nullptr);
bitmap->fillRect(nullptr, pal->getNearestIndex(RGB(92, 92, 92)));
CBofRect bmpRect(bitmap->getRect());
bitmap->drawRect(&bmpRect, pal->getNearestIndex(RGB(0, 0, 0)));
bitmap->fillRect(rect, pal->getNearestIndex(RGB(255, 255, 255)));
}
CBofRect bmpRect(bitmap->getRect());
const CBofString className = "CDevDlg";
CBagStorageDevDlg::create(className, &bmpRect, wnd, 0);
center();
setBackdrop(bitmap);
return _errCode;
}
void CDevDlg::onLButtonUp(uint32 /*nFlags*/, CBofPoint */*pPoint*/, void *) {
}
void CDevDlg::onMouseMove(uint32 /*nFlags*/, CBofPoint */*pPoint*/, void *) {
}
void CDevDlg::onClose() {
assert(isValidObject(this));
CBagVar *varDialogReturn = g_VarManager->getVariable("DIALOGRETURN");
if (varDialogReturn != nullptr) {
// If we need to parse the input for 2 words (Deven-7 Code words)
if (_useExtraFl) {
// Find the break
char *p = strchr(_achGuess, ',');
if ((p != nullptr) || ((p = strchr(_achGuess, ' ')) != nullptr)) {
*p = '\0';
p++;
// Set variable 2 (DIALOGRETURN2)
CBagVar *varDialogReturn2 = g_VarManager->getVariable("DIALOGRETURN2");
if (varDialogReturn2 != nullptr) {
varDialogReturn2->setValue(p);
}
}
}
// Set variable 1 (DIALOGRETURN)
varDialogReturn->setValue(_achGuess);
}
delete _guessText;
_guessText = nullptr;
CBagStorageDevDlg::onClose();
}
void CDevDlg::onKeyHit(uint32 keyCode, uint32 repCount) {
assert(isValidObject(this));
if (_guessCount < ACH_GUESS_MAX_CHARS) {
bool paintGuessFl = false;
const char *const MISC_KEYS = " \'$,-%.";
if (Common::isAlnum(keyCode) || strchr(MISC_KEYS, keyCode)) {
_achGuess[_guessCount] = toupper(keyCode);
_guessCount++;
paintGuessFl = true;
} else if (keyCode == BKEY_BACK && (_guessCount - 1) >= 0) {
_guessCount--;
_achGuess[_guessCount] = 0;
paintGuessFl = true;
}
if (paintGuessFl) {
paintText();
}
// Close dialog box when enter key is hit
if (keyCode == BKEY_ENTER) {
onClose();
}
}
// If it maxes out, clear it
if (_guessCount >= ACH_GUESS_MAX_CHARS) {
Common::fill(_achGuess, _achGuess + ACH_GUESS_MAX_CHARS, 0);
_guessCount = 0;
}
CBagStorageDevDlg::onKeyHit(keyCode, repCount);
}
void CDevDlg::paintText() {
assert(isValidObject(this));
char achTemp[ACH_GUESS_MAX_CHARS + 1];
snprintf(achTemp, ACH_GUESS_MAX_CHARS + 1, "%s", _achGuess);
_guessText->display(getBackdrop(), achTemp, 16, TEXT_MEDIUM);
}
void CDevDlg::setText(CBofString &text, CBofRect *textRect) {
assert(isValidObject(this));
_titleText = new CBofText;
_titleText->setupText(textRect, JUSTIFY_CENTER, FORMAT_DEFAULT);
_titleText->setColor(CTEXT_WHITE);
_titleText->SetSize(FONT_14POINT);
_titleText->setWeight(TEXT_BOLD);
_titleText->setText(text);
}
// Override on render to do the painting, but call the default anyway.
ErrorCode CDevDlg::onRender(CBofBitmap *bmp, CBofRect *rect) {
assert(isValidObject(this));
const ErrorCode errorCode = CBagStorageDevDlg::onRender(bmp, rect);
if (_titleText != nullptr) {
_titleText->display(getBackdrop());
}
return errorCode;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,63 @@
/* 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 BAGEL_BAGLIB_DEV_DLG_H
#define BAGEL_BAGLIB_DEV_DLG_H
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/boflib/gfx/text.h"
namespace Bagel {
namespace SpaceBar {
#define ACH_GUESS_MAX_CHARS 40
class CDevDlg : public CBagStorageDevDlg {
private:
// for text entry:
char _achGuess[ACH_GUESS_MAX_CHARS];
CBofText *_guessText;
int _guessCount;
int _buttonX;
int _buttonY;
bool _useExtraFl;
CBofText *_titleText;
public:
CDevDlg(int buttonX = -1, int buttonY = -1);
~CDevDlg();
ErrorCode createWindow(const char *bmp, CBofWindow *wnd, CBofPalette *pal, CBofRect *rect, bool useExtraFl);
void paintText();
void setText(CBofString &, CBofRect *);
void onKeyHit(uint32 keyCode, uint32 repCount) override;
void onMouseMove(uint32 flags, CBofPoint *point, void * = nullptr) override;
void onLButtonUp(uint32 flags, CBofPoint *point, void * = nullptr) override;
void onClose() override;
ErrorCode onRender(CBofBitmap *bmp, CBofRect *rect = nullptr) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,392 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/dossier_object.h"
#include "bagel/spacebar/baglib/rp_object.h"
#include "bagel/spacebar/baglib/master_win.h"
namespace Bagel {
namespace SpaceBar {
CBagDossierObject *CBagDossierObject::_curDossier;
void CBagDossierObject::initialize() {
_curDossier = nullptr;
}
CBagDossierObject::CBagDossierObject() {
_xObjType = DOSSIER_OBJ;
_dossierSetFl = false;
_indexRect.setRect(0, 0, 0, 0);
// Keep track of the original text rect.
_dossierRect.setRect(0, 0, 0, 0);
_dosRectInitFl = false;
setNotActive(false);
// Ptr to parent rp obj nullptr for now.
_residuePrintedObject = nullptr;
// Start with index line displayed
_showIndexFl = true;
}
CBagDossierObject::~CBagDossierObject() {
}
ParseCodes CBagDossierObject::setInfo(CBagIfstream &istr) {
bool objectUpdatedFl = false;
char localBuffer[256];
CBofString sStr(localBuffer, 256);
while (!istr.eof()) {
istr.eatWhite();
const char ch = (char)istr.peek();
switch (ch) {
// SIZE n - n point size of the txt
//
// -or-
//
// SUSPECTVAR is a variable that will be in the LOGPDA list of
// objects and will be tightly tied to residue printing. If a res print
// yields positive results on a character then set the rp field of the
// associated suspect object to true.
case 'S':
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("SIZE")) {
istr.eatWhite();
int size;
getIntFromStream(istr, size);
setPointSize((byte)size);
objectUpdatedFl = true;
} else if (!sStr.find("SUSPECTVAR")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
_sSuspectVar = sStr;
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
//
// NOTACTIVE KEYWORD MEANS DON'T DO ANYTHING ON MOUSE DOWN!!!
//
case 'N':
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("NOTACTIVE")) {
setNotActive(true);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
//
// FONT MONO or DEFAULT
//
case 'F':
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("FONT")) {
istr.eatWhite();
int fontId;
getIntFromStream(istr, fontId);
fontId = MapFont(fontId);
setFont(fontId);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
//
// INDEX line, required. This is the line that will show up in the
// log entry.
//
case 'I':
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("INDEX")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
// replace underlines with spaces.
sStr.replaceChar('_', ' ');
_indexLine = sStr;
objectUpdatedFl = true;
// If the next character is a '[' then we got another rect coming
// along. This rect is for the index string.
istr.eatWhite();
if ((char)istr.peek() == '[') {
CBofRect r;
getRectFromStream(istr, r);
_indexRect = r;
}
} else {
putbackStringOnStream(istr, sStr);
}
break;
//
// AS [CAPTION] - how to run the link
case 'A':
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("AS")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("CAPTION")) {
_bCaption = true;
objectUpdatedFl = true;
} else if (!sStr.find("TITLE")) {
_bTitle = true;
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, sStr);
putbackStringOnStream(istr, "AS ");
}
} else {
putbackStringOnStream(istr, sStr);
}
break;
//
// COLOR n - n color index
//
case 'C':
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("COLOR")) {
int nColor;
istr.eatWhite();
getIntFromStream(istr, nColor);
setColor(nColor);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
//
// no match return from function
//
default:
const ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
objectUpdatedFl = true;
} else { // rc==UNKNOWN_TOKEN
if (objectUpdatedFl)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
break;
}
}
return PARSING_DONE;
}
// Implement attach and detach just so we can set our own attributes
ErrorCode CBagDossierObject::attach() {
const ErrorCode errorCode = CBagTextObject::attach();
// Keep track of the original text rectangle (for the dossier).
if (_dosRectInitFl == false) {
_dossierRect = CBagTextObject::getRect();
_dosRectInitFl = true;
}
setVisible(false); // Don't display until needed.
setActive(false); // Not active until we need it.
return errorCode;
}
ErrorCode CBagDossierObject::detach() {
const ErrorCode errorCode = CBagTextObject::detach();
setVisible(false); // Make this invisible, don't want it redrawn.
return errorCode;
}
// Called to splash one of these guys to the screen
ErrorCode CBagDossierObject::update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect, int n) {
if (_showIndexFl) {
if (_dossierSetFl == false) {
// Set the text to be the index line.
setPSText(&_indexLine);
_dossierSetFl = true;
}
} else if (_dossierSetFl == false) {
// Set the text to be nullptr, this forces the bagtx code to
// paint the text file.
setPSText(nullptr);
CBagTextObject::attach();
_dossierSetFl = true;
}
return CBagTextObject::update(bmp, pt, srcRect, n);
}
CBofRect CBagDossierObject::getRect() {
CBofRect rect;
const CBofPoint pos = getPosition();
if (_showIndexFl) {
rect = _indexRect;
rect.offsetRect(pos);
} else {
rect = _dossierRect;
}
return rect;
}
void CBagDossierObject::onLButtonUp(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void */*pInfo*/) {
// If this is an inactive object (such as "plus residue too old" or "negative")
// then ignore the mousedown.
if (getNotActive()) {
return;
}
showDossierText();
}
// utility routine for activating dossier objects
void CBagDossierObject::activateDossierObject(CBagLog *logWld) {
if (logWld) {
logWld->activateLocalObject(this);
}
if (CBagRPObject::getLogState() == RP_READ_DOSSIER) {
setFloating(false); // This is not floating
} else {
setFloating(); // This is not floating
}
setVisible(); // can see this thing now...
setActive(); // make sure it counts for something
// Starting state will ALWAYS be index first
_dossierSetFl = false;
_showIndexFl = true;
}
void CBagDossierObject::deactivateDossierObject(CBagLog *logWld) {
if (CBagRPObject::getLogState() == RP_READ_DOSSIER) {
setFloating(false); // This is not floating
} else {
setFloating(); // This is not floating
}
setVisible(false); // Cover it up
setActive(false); // Make sure it counts for something
setLocal(false); // Not local anymore
}
// Called from script to deactivate a dossier view screen.
void CBagDossierObject::deactivateCurDossier() {
// If we have a current dossier, then turn it off and activate the
// previous rp object.
if (_curDossier != nullptr) {
CBagLog *logWld = nullptr;
CBagRPObject *residuePrintedObj = ((CBagRPObject *)(_curDossier->_residuePrintedObject));
if (residuePrintedObj) {
if (residuePrintedObj->zoomed()) {
logWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
} else {
logWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
}
}
_curDossier->deactivateDossierObject(logWld);
// When we hit the update code, we're gonna need to reevaluate this
// guys current view status.
_curDossier->_showIndexFl = true;
_curDossier->_dossierSetFl = false;
((CBagRPObject *)(_curDossier->_residuePrintedObject))->activateRPObject();
_curDossier = nullptr;
}
}
void CBagDossierObject::showDossierText() {
// Make sure our script knows where we're going with this.
CBagRPObject::setLogState(RP_READ_DOSSIER);
// We got a mouse down on one of our dossier's, so now we have to deactivate
// everything that is in the residue print object that this dossier is
// contained in.
bool zoomedFl = false;
if (_residuePrintedObject) {
zoomedFl = ((CBagRPObject *)_residuePrintedObject)->zoomed();
((CBagRPObject *)_residuePrintedObject)->deactivateRPObject();
}
// Get the appropriate storage device
CBagLog *logWld;
if (zoomedFl) {
logWld = (CBagLog *)g_SDevManager->getStorageDevice(LOGZ_WLD);
} else {
logWld = (CBagLog *)g_SDevManager->getStorageDevice(LOG_WLD);
}
// Now reactivate this object.
activateDossierObject(logWld);
// Mark this one as our current dossier
_curDossier = this;
// Make sure the text file is displayed, not the index line. See the
// update code to see why this makes this happen.
_dossierSetFl = false;
_showIndexFl = false;
// Let the residue printing object know which one we're displaying.
CBagRPObject *pRPObj = (CBagRPObject *)_residuePrintedObject;
pRPObj->setActiveDossier(this);
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,90 @@
/* 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 BAGEL_BAGLIB_DOSSIER_OBJECT_H
#define BAGEL_BAGLIB_DOSSIER_OBJECT_H
#include "bagel/spacebar/baglib/text_object.h"
#include "bagel/spacebar/baglib/log_msg.h"
namespace Bagel {
namespace SpaceBar {
class CBagDossierObject : public CBagTextObject {
private:
CBofString _indexLine;
CBofRect _indexRect;
CBofRect _dossierRect;
CBagObject *_residuePrintedObject;
bool _dossierSetFl : 1;
bool _notActiveFl : 1;
bool _showIndexFl : 1;
bool _dosRectInitFl : 1;
public:
CBofString _sSuspectVar;
public:
CBagDossierObject();
virtual ~CBagDossierObject();
/**
* Takes in info and then removes the relative information and returns
* the info without the relevant info.
*/
ParseCodes setInfo(CBagIfstream &istr) override;
ErrorCode attach() override;
ErrorCode detach() override;
ErrorCode update(CBofBitmap *, CBofPoint, CBofRect * = nullptr, int = -1) override;
void onLButtonUp(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr) override; // run menu if available
CBofRect getRect() override;
void setNotActive(bool b) {
_notActiveFl = b;
}
bool getNotActive() const {
return _notActiveFl;
}
void activateDossierObject(CBagLog *logWld);
void deactivateDossierObject(CBagLog *logWld);
void setResiduePrintedObject(CBagObject *p) {
_residuePrintedObject = p;
};
static void deactivateCurDossier();
void showDossierText();
static void initialize();
static CBagDossierObject *_curDossier;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,109 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/event_sdev.h"
#include "bagel/spacebar/baglib/pda.h"
#include "bagel/spacebar/baglib/sound_object.h"
namespace Bagel {
namespace SpaceBar {
bool CBagEventSDev::_evalTurnEventsFl;
ErrorCode CBagEventSDev::attach() {
const ErrorCode errorCode = CBagStorageDev::attach();
// Set the firstpaint flag and attach objects to allow
// for immediate run objects to run
if (_bFirstPaint) {
_bFirstPaint = false;
attachActiveObjects();
}
return errorCode;
}
ErrorCode CBagEventSDev::evaluateExpressions() {
// If a Zelda movie is playing, don't execute the event world
if (CBagPDA::isMoviePlaying())
return ERR_NONE;
ErrorCode errorCode = ERR_NONE;
const int count = getObjectCount();
for (int i = 0; i < count; ++i) {
CBagObject *posObj = getObjectByPos(i);
if (posObj != nullptr) {
// Find the local Expression objects
// This code says... only evaluate if we're in an if statement, this must be wrong.
if (posObj->getExpression() == nullptr || posObj->getExpression()->evaluate(posObj->isNegative())) {
if (!posObj->isAttached()) {
posObj->setActive();
posObj->attach();
}
if (posObj->isImmediateRun())
posObj->runObject();
} else if (posObj->isAttached() && (posObj->getType() != SOUND_OBJ || !((CBagSoundObject *)posObj)->isPlaying())) {
posObj->setActive(false);
posObj->detach();
}
} else
errorCode = ERR_FFIND;
}
return errorCode;
}
ErrorCode CBagTurnEventSDev::evaluateExpressions() {
// If a zelda movie is playing, don't execute the turncount world
if (CBagPDA::isMoviePlaying()) {
return ERR_UNKNOWN;
}
ErrorCode errorCode = ERR_NONE;
const int count = getObjectCount();
for (int i = 0; i < count; ++i) {
CBagObject *posObj = getObjectByPos(i);
if (posObj != nullptr) {
// Find the local Expression objects
// This code says... only evaluate if we're in an if statement, this must be wrong.
if (posObj->getExpression() == nullptr || posObj->getExpression()->evaluate(posObj->isNegative())) {
if (!posObj->isAttached()) {
posObj->setActive();
posObj->attach();
}
if (posObj->isImmediateRun())
posObj->runObject();
} else if (posObj->isAttached() && (posObj->getType() != SOUND_OBJ || !((CBagSoundObject *)posObj)->isPlaying())) {
posObj->setActive(false);
posObj->detach();
}
} else
errorCode = ERR_FFIND;
}
return errorCode;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,95 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 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 BAGEL_BAGLIB_EVENT_SDEV_H
#define BAGEL_BAGLIB_EVENT_SDEV_H
#include "bagel/spacebar/baglib/storage_dev_win.h"
namespace Bagel {
namespace SpaceBar {
class CBagEventSDev : public CBagStorageDev {
private:
static bool _evalTurnEventsFl;
public:
CBagEventSDev() : CBagStorageDev() {
}
virtual ~CBagEventSDev() {
}
static void initialize() {
_evalTurnEventsFl = false;
}
/**
* Called to overload new set backgrounds. Calls the set backdrop pure
* virtual function by default.
*/
ErrorCode attach() override;
ErrorCode setBackground(CBofBitmap * /* bmp, unused */) override {
return ERR_NONE;
}
CBofBitmap *getBackground() override {
return nullptr;
}
/**
* Evaluate only the expression object of this storage device
* @return Returns and error code if there is an invalid object in the list
*/
virtual ErrorCode evaluateExpressions();
// Gives timer code a method to launch tim
static void setEvalTurnEvents(bool b = true) {
_evalTurnEventsFl = b;
}
static bool getEvalTurnEvents() {
return _evalTurnEventsFl;
}
};
class CBagTurnEventSDev : public CBagStorageDev {
public:
CBagTurnEventSDev() : CBagStorageDev() {
}
virtual ~CBagTurnEventSDev() {
}
ErrorCode setBackground(CBofBitmap * /* bmp, unused */) override {
return ERR_NONE;
}
CBofBitmap *getBackground() override {
return nullptr;
}
virtual ErrorCode evaluateExpressions();
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,138 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/exam.h"
#include "bagel/spacebar/dialogs/opt_window.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
namespace Bagel {
namespace SpaceBar {
bool CBagExam::initExam() {
CBofRect paintRect(155, 55, 155 + 330 - 1, 55 + 250 - 1);
paintBitmap(CBagel::getBagApp()->getMasterWnd()->getCurrentGameWindow(), buildSysDir("SSBORDER.BMP"), &paintRect);
Common::Event e;
while (g_system->getEventManager()->pollEvent(e)) {
// Flush events, though not sure why we need it
}
getParent()->disable();
getParent()->flushAllMessages();
markBegEnd();
setRotationRects();
_bLoop = true;
_bEscCanStop = true;
pause();
CBofCursor::show();
doModal();
CBofCursor::hide();
return true;
}
void CBagExam::onReSize(CBofSize *size) {
CBofMovie::onReSize(size);
setRotationRects();
}
bool CBagExam::setRotationRects() {
// Get the windows rect
const CBofRect clientRect = getClientRect();
// Left quarter of the video window
_leftRect.left = clientRect.left;
_leftRect.top = clientRect.top;
_leftRect.right = clientRect.left + ((clientRect.right - clientRect.left) / 4);
_leftRect.bottom = clientRect.bottom;
// Right quarter of the video window
_rightRect.left = clientRect.right - ((clientRect.bottom - clientRect.left) / 4);
_rightRect.top = clientRect.top;
_rightRect.right = clientRect.right;
_rightRect.bottom = clientRect.bottom;
return true;
}
bool CBagExam::markBegEnd() {
_end = _pSmk->getFrameCount() - 1;
_start = 0;
return true;
}
void CBagExam::onButtonUp(uint32 /*n flags, unused */, CBofPoint */* point, unused */) {
// Clean up and exit
_bLoop = false;
stop();
onMovieDone();
}
bool CBagExam::rotateLeft() {
if (_eMovStatus != FORWARD)
return play();
return true;
}
bool CBagExam::rotateRight() {
if (_eMovStatus != REVERSE)
return reverse();
return true;
}
bool CBagExam::rotateStop() {
if (_eMovStatus == FORWARD || _eMovStatus == REVERSE)
// The movie is currently playing
return pause();
return true;
}
void CBagExam::onMouseMove(uint32 /* flags, unused */, CBofPoint *point, void */* extraInfo, unused */) {
assert(isValidObject(this));
assert(point != nullptr);
// No more cursor in Examine movies
if (point->x <= _leftRect.right) {
// Left rect, play reverse
rotateLeft();
} else if (point->x >= _rightRect.left) {
// Right rect, play forward
rotateRight();
} else if (_eMovStatus == FORWARD || _eMovStatus == REVERSE) {
rotateStop();
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,100 @@
/* 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 BAGEL_BAGLIB_EXAM_H
#define BAGEL_BAGLIB_EXAM_H
#include "bagel/spacebar/boflib/gui/movie.h"
namespace Bagel {
namespace SpaceBar {
class CBagExam : public CBofMovie {
protected:
CBofRect _leftRect;
CBofRect _rightRect;
uint32 _start;
uint32 _end;
public:
CBagExam(CBofWindow *pParent = nullptr) : CBofMovie(pParent),
_leftRect(0, 0, 0, 0), _rightRect(0, 0, 0, 0), _start(0), _end(0) {
}
CBagExam(CBofWindow *pParent, const char *sFilename) : CBofMovie(pParent, sFilename),
_leftRect(0, 0, 0, 0), _rightRect(0, 0, 0, 0), _start(0), _end(0) {
}
CBagExam(CBofWindow *pParent, const char *sFilename, CBofRect *pBounds) : CBofMovie(pParent, sFilename, pBounds),
_leftRect(0, 0, 0, 0), _rightRect(0, 0, 0, 0), _start(0), _end(0) {
}
~CBagExam() {
}
/**
* Initialize exam object after opened and ready to play
* @return Success/failure
*/
virtual bool initExam();
/**
* Called when the mouse is moved over window, check if the
* cursor is in one of the rectangle and rotate object accordingly
*/
void onMouseMove(uint32 /* flags */, CBofPoint *point, void */* extraInfo */ = nullptr) override;
/**
* Resize the examination window
*/
void onReSize(CBofSize *size) override;
void onButtonUp(uint32 /* flags */, CBofPoint */* point */) override;
/**
* Set the rectangles that determine "hot" mouse locations
* @return Success/failure
*/
bool setRotationRects();
/**
* Store off the start and end frames of the movies
* @return Success/failure
*/
bool markBegEnd();
/**
* Rotate the object to the right (play movie)
*/
bool rotateRight();
/**
* Rotate the object to the left (reverse movie)
*/
bool rotateLeft();
/**
* Stop the rotation of the object (stop movie)
*/
bool rotateStop();
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,747 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/expression.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/baglib/sound_object.h"
#include "bagel/boflib/sound.h"
#include "bagel/bagel.h"
namespace Bagel {
namespace SpaceBar {
CBagVar *CBagExpression::_tempVar; // Used as a default param
void CBagExpression::initialize() {
// used as a default param
_tempVar = new CBagVar("CBagExpr::TempVar", "", false);
}
void CBagExpression::shutdown() {
delete _tempVar;
}
CBagExpression::CBagExpression(CBagExpression *prevExpr, bool prevNegFl) {
_negativeFl = false;
_prevExpression = prevExpr;
_prevNegativeFl = prevNegFl;
}
CBagExpression::~CBagExpression() {
}
bool CBagExpression::evaluate(CBagVar *leftHandOper, CBagVar *rightHandOper, OPERATION oper, CBagVar &result) {
bool retVal = false;
// If the variable is named "RANDOM", generate a random number for its value
if (leftHandOper->getName() == "RANDOM")
leftHandOper->setValue(g_engine->getRandomNumber());
if (rightHandOper->getName() == "RANDOM")
rightHandOper->setValue(g_engine->getRandomNumber());
switch (oper) {
case OP_NONE:
break;
case OP_ASSIGN:
retVal = onAssign(leftHandOper, rightHandOper, result);
break;
case OP_EQUAL:
retVal = onEqual(leftHandOper, rightHandOper, result);
break;
case OP_NOT_EQUAL:
retVal = onNotEqual(leftHandOper, rightHandOper, result);
break;
case OP_LESS_THAN:
retVal = onLessThan(leftHandOper, rightHandOper, result);
break;
case OP_LESS_THAN_EQUAL:
retVal = onLessThanEqual(leftHandOper, rightHandOper, result);
break;
case OP_GREATER_THAN:
retVal = onGreaterThan(leftHandOper, rightHandOper, result);
break;
case OP_GREATER_THAN_EQUAL:
retVal = onGreaterThanEqual(leftHandOper, rightHandOper, result);
break;
case OP_PLUS_ASSIGN:
retVal = onPlusAssign(leftHandOper, rightHandOper, result);
break;
case OP_MINUS_ASSIGN:
retVal = onMinusAssign(leftHandOper, rightHandOper, result);
break;
case OP_PLUS:
retVal = onPlus(leftHandOper, rightHandOper, result);
break;
case OP_MINUS:
retVal = onMinus(leftHandOper, rightHandOper, result);
break;
case OP_MULTIPLY:
retVal = onMultiply(leftHandOper, rightHandOper, result);
break;
case OP_DIVIDE:
retVal = onDivide(leftHandOper, rightHandOper, result);
break;
case OP_MOD:
retVal = onMod(leftHandOper, rightHandOper, result);
break;
case OP_CONTAINS:
retVal = onContains(leftHandOper, rightHandOper, result);
break;
case OP_HAS:
retVal = onHas(leftHandOper, rightHandOper, result);
break;
case OP_STATUS:
retVal = onStatus(leftHandOper, rightHandOper, result);
break;
default:
break;
}
return retVal;
}
CBagVar *CBagExpression::getVariable(int itemPos) {
CBagVar *curVar = _varList.getNodeItem(itemPos);
// If the variable is a reference (OBJ.PROPERTY)
if (curVar->isReference()) {
char frontStr[256];
Common::strcpy_s(frontStr, curVar->getName());
char *p = strstr(frontStr, "~~");
if (p != nullptr) {
char backStr[256];
Common::strcpy_s(backStr, p + 2);
*p = '\0';
const CBofString stringObject(frontStr, 256);
const CBofString stringProperty(backStr, 256);
const int newVal = g_SDevManager->getObjectValue(stringObject, stringProperty);
curVar->setValue(newVal);
}
}
return curVar;
}
CBagExpression::OPERATION CBagExpression::getOperation(int itemPos) {
assert(false);
return _operList.getNodeItem(itemPos);
}
bool CBagExpression::evaluate(bool negFl, CBagVar &result) {
bool retVal = false;
// There must be an expression for every variable after the first
assert(_varList.getCount() - 1 == _operList.getCount());
int count = 0;
CBagVar *leftHandOper = getVariable(count++);
result = *leftHandOper;
bool parentCheckFl = true;
if (_prevExpression) {
parentCheckFl = _prevExpression->evaluate(_prevNegativeFl, result);
}
if (parentCheckFl) {
bool subValFl;
int nodeCount = 0;
while (count < _varList.getCount()) {
CBagVar *rightHandOper = getVariable(count++);
OPERATION oper = _operList.getNodeItem(nodeCount++);
CBagVar *rightHandOper2;
switch (oper) {
case OP_AND:
rightHandOper2 = getVariable(count++);
oper = _operList.getNodeItem(nodeCount++);
subValFl = evaluate(rightHandOper, rightHandOper2, oper, result);
retVal &= subValFl;
break;
case OP_OR:
rightHandOper2 = getVariable(count++);
oper = _operList.getNodeItem(nodeCount++);
subValFl = evaluate(rightHandOper, rightHandOper2, oper, result);
retVal |= subValFl;
break;
default:
retVal = evaluate(leftHandOper, rightHandOper, oper, result);
break;
}
}
if (negFl)
// Evaluate before and with parent
retVal = !retVal;
retVal &= parentCheckFl;
}
return retVal;
}
bool CBagExpression::evalLeftToRight(bool negFl, CBagVar &result) {
bool retVal = false;
OPERATION oper = OP_NONE;
// There must be an expression for every variable after the first
assert(_varList.getCount() - 1 == _operList.getCount());
int varCount = 0;
CBagVar *leftHandOper = getVariable(varCount++);
result = *leftHandOper;
bool parentCheckFl = true;
if (_prevExpression) {
parentCheckFl = _prevExpression->evaluate(_prevNegativeFl, result);
}
if (parentCheckFl) {
bool bFirstTime = true;
int nodeCount = 0;
while (varCount < _varList.getCount()) {
CBagVar compLeftHandOper;
CBagVar *rightHandOper = getVariable(varCount++);
const OPERATION prevOper = oper; // save previous operator
oper = _operList.getNodeItem(nodeCount++);
if (bFirstTime) {
compLeftHandOper = *leftHandOper;
bFirstTime = false;
} else {
// Based on what we have for a previous operator, either use
// the left hand expression or the result of the previous expression.
switch (prevOper) {
case OP_MINUS:
case OP_MULTIPLY:
case OP_DIVIDE:
case OP_MOD:
case OP_PLUS:
compLeftHandOper = result;
break;
case OP_NONE:
case OP_ASSIGN:
case OP_EQUAL:
case OP_NOT_EQUAL:
case OP_LESS_THAN:
case OP_LESS_THAN_EQUAL:
case OP_GREATER_THAN:
case OP_GREATER_THAN_EQUAL:
case OP_PLUS_ASSIGN:
case OP_MINUS_ASSIGN:
case OP_CONTAINS:
case OP_HAS:
case OP_STATUS:
default:
compLeftHandOper = *leftHandOper;
break;
}
}
bool boolVal;
CBagVar *rightHandOper2;
switch (oper) {
case OP_AND:
rightHandOper2 = getVariable(varCount++);
oper = _operList.getNodeItem(nodeCount++);
boolVal = evaluate(rightHandOper, rightHandOper2, oper, result);
retVal &= boolVal;
break;
case OP_OR:
rightHandOper2 = getVariable(varCount++);
oper = _operList.getNodeItem(nodeCount++);
boolVal = evaluate(rightHandOper, rightHandOper2, oper, result);
// or this don't not it!!!
retVal |= boolVal;
break;
default:
retVal = evaluate(&compLeftHandOper, rightHandOper, oper, result);
break;
}
}
if (negFl)
// Evaluate before and with parent
retVal = !retVal;
retVal &= parentCheckFl;
}
return retVal;
}
bool CBagExpression::negEvaluate(CBagVar &result) {
return evaluate(false, result);
}
bool CBagExpression::onAssign(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar & /* resultOper, unused*/) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
char buffer[256];
Common::strcpy_s(buffer, rightHandOper->getValue());
assert(strlen(buffer) < 256);
const CBofString newLeftHandValue(buffer, 256);
leftHandOper->setValue(newLeftHandValue);
return true;
}
bool CBagExpression::onEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
const bool retVal = leftHandOper->getValue() == rightHandOper->getValue();
resultOper.setBoolValue(retVal);
return retVal;
}
bool CBagExpression::onNotEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
const bool retVal = leftHandOper->getValue() != rightHandOper->getValue();
resultOper.setBoolValue(retVal);
return retVal;
}
bool CBagExpression::onLessThan(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
const bool retVal = leftHandOper->getNumValue() < rightHandOper->getNumValue();
resultOper.setBoolValue(retVal);
return retVal;
}
bool CBagExpression::onGreaterThan(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
const bool retVal = leftHandOper->getNumValue() > rightHandOper->getNumValue();
resultOper.setBoolValue(retVal);
return retVal;
}
bool CBagExpression::onLessThanEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
const bool retVal = leftHandOper->getNumValue() <= rightHandOper->getNumValue();
resultOper.setBoolValue(retVal);
return retVal;
}
bool CBagExpression::onGreaterThanEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
const bool retVal = leftHandOper->getNumValue() >= rightHandOper->getNumValue();
resultOper.setBoolValue(retVal);
return retVal;
}
bool CBagExpression::onPlusAssign(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
if (leftHandOper->isNumeric() && rightHandOper->isNumeric()) {
const int leftHandNum = leftHandOper->getNumValue();
const int rightHandNum = rightHandOper->getNumValue();
leftHandOper->setValue(leftHandNum + rightHandNum);
resultOper.setValue(leftHandOper->getNumValue());
}
return true;
}
bool CBagExpression::onMinusAssign(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
if (leftHandOper->isNumeric() && rightHandOper->isNumeric()) {
const int leftHandNum = leftHandOper->getNumValue();
const int rightHandNum = rightHandOper->getNumValue();
leftHandOper->setValue(leftHandNum - rightHandNum);
resultOper.setValue(leftHandOper->getNumValue());
}
return true;
}
bool CBagExpression::onContains(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar & /* resultOper, unused */) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
CBagStorageDev *sDev = g_SDevManager->getStorageDevice(leftHandOper->getValue());
if (sDev == nullptr)
return false;
CBagObject *curObj = sDev->getObject(rightHandOper->getValue());
if ((curObj != nullptr) && curObj->isActive())
return true;
return false;
}
bool CBagExpression::onHas(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar & /* resultOper, unused */) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
CBagStorageDev *sDev = g_SDevManager->getStorageDevice(leftHandOper->getValue());
if (sDev == nullptr)
return false;
CBagObject *curObj = sDev->getObjectByType(rightHandOper->getValue(), true);
if (curObj == nullptr)
return false;
return true;
}
bool CBagExpression::onStatus(CBagVar *pLHOper, CBagVar * /* rightHandOper, unused */, CBagVar & /* resultOper, unused */) {
assert(pLHOper != nullptr);
CBagStorageDev *sDev = g_SDevManager->getStorageDeviceContaining(pLHOper->getValue());
if (sDev == nullptr)
return false;
CBagObject *curObj = sDev->getObject(pLHOper->getValue());
if (curObj == nullptr)
return false;
return false;
}
bool CBagExpression::onCurrSDev(CBagVar * /* leftHandOper, unused*/, CBagVar * /* rightHandOper, unused */, CBagVar & /* resultOper, unused */) {
return true;
}
bool CBagExpression::onPlus(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
if (leftHandOper->isNumeric() && rightHandOper->isNumeric()) {
const int leftHandNum = leftHandOper->getNumValue();
const int rightHandNum = rightHandOper->getNumValue();
resultOper.setValue(leftHandNum + rightHandNum);
}
return true;
}
bool CBagExpression::onMinus(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
if (leftHandOper->isNumeric() && rightHandOper->isNumeric()) {
const int leftHandNum = leftHandOper->getNumValue();
const int rightHandNum = rightHandOper->getNumValue();
resultOper.setValue(leftHandNum - rightHandNum);
}
return true;
}
bool CBagExpression::onMultiply(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
if (leftHandOper->isNumeric() && rightHandOper->isNumeric()) {
const int leftHandNum = leftHandOper->getNumValue();
const int rightHandNum = rightHandOper->getNumValue();
resultOper.setValue(leftHandNum * rightHandNum);
}
return true;
}
bool CBagExpression::onDivide(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
if (leftHandOper->isNumeric() && rightHandOper->isNumeric()) {
const int leftHandNum = leftHandOper->getNumValue();
const int rightHandNum = rightHandOper->getNumValue();
// Divide by Zero error?
assert(rightHandNum != 0);
resultOper.setValue(leftHandNum / rightHandNum);
}
return true;
}
bool CBagExpression::onMod(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
if (leftHandOper->isNumeric() && rightHandOper->isNumeric()) {
const int leftHandNum = leftHandOper->getNumValue();
const int rightHandNum = rightHandOper->getNumValue();
// Divide by Zero error?
assert(rightHandNum != 0);
resultOper.setValue(leftHandNum % rightHandNum);
}
return true;
}
bool CBagExpression::onAnd(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar & /* resultOper, unused */) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
return (!leftHandOper->getValue().find("true") && !rightHandOper->getValue().find("true"));
}
bool CBagExpression::onOr(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar & /* resultOper, unused */) {
assert((leftHandOper != nullptr) && (rightHandOper != nullptr));
return (!leftHandOper->getValue().find("true") || !rightHandOper->getValue().find("true"));
}
ParseCodes CBagExpression::setInfo(CBagIfstream &istr) {
char buffer[256];
buffer[0] = 0;
CBofString tmpStr(buffer, 256);
ParseCodes parseCode = PARSING_DONE;
bool doneFl = false;
while (!doneFl && parseCode == PARSING_DONE) {
istr.eatWhite();
int ch = istr.peek();
switch (ch) {
case '(': {
istr.getCh();
istr.eatWhite();
getAlphaNumFromStream(istr, tmpStr);
CBagVar *curVar = g_VarManager->getVariable(tmpStr);
if (!curVar) {
// This must be a reference, make a new variable
if (tmpStr.find("~~") > 0) {
curVar = new CBagVar;
curVar->setName(tmpStr);
curVar->setReference();
} else {
// This is an error condition, constants can only be rhopers
curVar = new CBagVar;
curVar->setName(tmpStr);
curVar->setValue(tmpStr);
curVar->setConstant();
}
}
_varList.addToTail(curVar);
istr.eatWhite();
ch = istr.peek();
while ((ch != ')') && parseCode == PARSING_DONE) {
OPERATION curOper;
getOperatorFromStream(istr, curOper);
if (curOper == OP_NONE) {
parseCode = UNKNOWN_TOKEN;
break;
}
_operList.addToTail(curOper);
istr.eatWhite();
getAlphaNumFromStream(istr, tmpStr);
curVar = g_VarManager->getVariable(tmpStr);
if (!curVar) {
if (tmpStr.find("~~") > 0) {
// This must be a reference, make a new variable
curVar = new CBagVar;
curVar->setName(tmpStr);
curVar->setReference();
} else {
// This must be a constant, make a new variable
curVar = new CBagVar;
curVar->setName(tmpStr);
curVar->setValue(tmpStr);
curVar->setConstant();
}
}
_varList.addToTail(curVar);
istr.eatWhite();
ch = istr.peek();
} // while parsing inner circle
if (ch == ')') {
istr.getCh();
doneFl = true;
}
break;
}
case 'N':
getAlphaNumFromStream(istr, tmpStr);
if (!tmpStr.find("NOT")) {
_negativeFl = !_negativeFl;
istr.eatWhite();
break;
}
// FIXME: Is this intentional?
// fallthrough
default:
parseCode = UNKNOWN_TOKEN;
break;
}
}
if (parseCode != PARSING_DONE) {
parseAlertBox(istr, "Error in expression:", __FILE__, __LINE__);
}
istr.eatWhite();
return parseCode;
}
ErrorCode CBagExpression::getOperatorFromStream(CBagIfstream &istr, OPERATION &oper) {
ErrorCode errorCode = ERR_NONE;
char localBuff[256];
localBuff[0] = 0;
CBofString localStr(localBuff, 256);
oper = OP_NONE;
istr.eatWhite();
getOperStrFromStream(istr, localStr);
if (localStr.isEmpty()) {
getAlphaNumFromStream(istr, localStr);
istr.eatWhite();
}
if (!localStr.find("-=")) {
oper = OP_MINUS_ASSIGN;
} else if (!localStr.find("+=")) {
oper = OP_PLUS_ASSIGN;
} else if (!localStr.find(">=")) {
oper = OP_GREATER_THAN_EQUAL;
} else if (!localStr.find("<=")) {
oper = OP_LESS_THAN_EQUAL;
} else if (!localStr.find("!=")) {
oper = OP_NOT_EQUAL;
} else if (!localStr.find("==")) {
oper = OP_EQUAL;
} else if (!localStr.find(">")) {
oper = OP_GREATER_THAN;
} else if (!localStr.find("<")) {
oper = OP_LESS_THAN;
} else if (!localStr.find("=")) {
oper = OP_ASSIGN;
} else if (!localStr.find("+")) {
oper = OP_PLUS;
} else if (!localStr.find("-")) {
oper = OP_MINUS;
} else if (!localStr.find("*")) {
oper = OP_MULTIPLY;
} else if (!localStr.find("/")) {
oper = OP_DIVIDE;
} else if (!localStr.find("%")) {
oper = OP_MOD;
} else if (!localStr.find("CONTAINS")) {
// SDev contains object
oper = OP_CONTAINS;
} else if (!localStr.find("HAS")) {
// SDev has type of object
oper = OP_HAS;
} else if (!localStr.find("OR")) {
oper = OP_OR;
} else if (!localStr.find("STATUS")) {
oper = OP_STATUS;
} else if (!localStr.find("AND")) {
oper = OP_AND;
}
if (oper == OP_NONE)
errorCode = ERR_UNKNOWN;
return errorCode;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,133 @@
/* 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 BAGEL_BAGLIB_EXPRESSION_H
#define BAGEL_BAGLIB_EXPRESSION_H
#include "bagel/spacebar/baglib/parse_object.h"
#include "bagel/spacebar/baglib/var.h"
#include "bagel/spacebar/boflib/list.h"
namespace Bagel {
namespace SpaceBar {
class CBagExpression : public CBagParseObject, public CBofObject {
public:
enum OPERATION {
OP_NONE,
OP_ASSIGN,
OP_EQUAL,
OP_NOT_EQUAL,
OP_LESS_THAN,
OP_LESS_THAN_EQUAL,
OP_GREATER_THAN,
OP_GREATER_THAN_EQUAL,
OP_PLUS_ASSIGN,
OP_MINUS_ASSIGN,
OP_CONTAINS,
OP_HAS,
OP_CURR_SDEV,
OP_PLUS,
OP_MINUS,
OP_MULTIPLY,
OP_DIVIDE,
OP_AND,
OP_OR,
OP_MOD,
OP_STATUS
};
private:
CBofList<CBagVar *> _varList; // Right hand operator
CBofList<OPERATION> _operList; // Operation to be preformed
CBagExpression *_prevExpression; // Not null when when this is an enclosed expression
bool _prevNegativeFl; // True if the operation should return Negative results
bool _negativeFl; // True if the operation should return Negative results
bool evaluate(CBagVar *leftHandOper, CBagVar *rightHandOper, OPERATION oper, CBagVar &result);
public:
static CBagVar *_tempVar; // Used as a default param
static void initialize();
static void shutdown();
CBagExpression(CBagExpression *prevExpr = nullptr, bool prevNegFl = false);
virtual ~CBagExpression();
bool evaluate(bool negFl = false, CBagVar &result = *_tempVar);
/**
* Same as evaluate above except it evaluates left to right and preserves
* the value of the previous evaluation in the loop. Provides partial
* evaluation hierarchy support.
*/
bool evalLeftToRight(bool negFl = false, CBagVar &result = *_tempVar);
bool negEvaluate(CBagVar &result = *_tempVar);
void setNegative(bool b = true) {
_negativeFl = b;
}
bool isNegative() const {
return _negativeFl;
}
CBagVar *getVariable(int itemPos);
OPERATION getOperation(int itemPos);
ParseCodes setInfo(CBagIfstream &istr) override;
ErrorCode getOperatorFromStream(CBagIfstream &istr, OPERATION &oper);
CBagExpression *getPrevExpression() const {
return _prevExpression;
}
void setPrevExpression(CBagExpression *expr) {
_prevExpression = expr;
}
virtual bool onAssign(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onNotEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onLessThan(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onGreaterThan(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onLessThanEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onGreaterThanEqual(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onPlusAssign(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onMinusAssign(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onContains(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onHas(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onCurrSDev(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onPlus(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onMinus(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onMultiply(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onDivide(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onMod(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onAnd(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onOr(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
virtual bool onStatus(CBagVar *leftHandOper, CBagVar *rightHandOper, CBagVar &resultOper);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,105 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/expression_object.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/var.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
namespace Bagel {
namespace SpaceBar {
CBagExpressionObject::CBagExpressionObject() : CBagObject() {
_xObjType = EXPRESS_OBJ;
_expression = nullptr;
setConditional(false);
setVisible(false);
setTimeless(true);
}
CBagExpressionObject::~CBagExpressionObject() {
delete _expression;
_expression = nullptr;
CBagObject::detach();
}
bool CBagExpressionObject::runObject() {
if (_expression != nullptr) {
CBagVar localVar;
_expression->evaluate(false, localVar);
if (!isConditional()) {
if (getFileName().isEmpty())
return false;
const int nIndex = getFileName().find("~~");
if (nIndex > 0) {
// This is a reference
const CBofString objectStr = getFileName().left(nIndex);
const CBofString propertyStr = getFileName().mid(nIndex + 2);
g_SDevManager->setObjectValue(objectStr, propertyStr, localVar.getNumValue());
} else {
CBagVar *pVar = g_VarManager->getVariable(getFileName());
if (pVar)
pVar->setValue(localVar.getValue());
}
}
}
return CBagObject::runObject();
}
ParseCodes CBagExpressionObject::setInfo(CBagIfstream &istr) {
bool objectUpdatedFl = false;
while (!istr.eof()) {
const char ch = (char)istr.peek();
if (ch == '(') {
//
// AS - n number of slides in sprite
//
_expression = new CBagExpression();
_expression->setInfo(istr);
objectUpdatedFl = true;
} else {
const ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
objectUpdatedFl = true;
} else { // rc==UNKNOWN_TOKEN
if (objectUpdatedFl)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
}
}
return PARSING_DONE;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,58 @@
/* 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 BAGEL_BAGLIB_EXPRESSION_OBJECT_H
#define BAGEL_BAGLIB_EXPRESSION_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/baglib/expression.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagExpressionObject is an object that can be place within the slide window.
*/
class CBagExpressionObject : public CBagObject {
private:
CBagExpression *_expression;
bool _conditionalFl;
public:
CBagExpressionObject();
virtual ~CBagExpressionObject();
bool runObject() override;
ParseCodes setInfo(CBagIfstream &istr) override;
bool isConditional() const {
return _conditionalFl;
}
void setConditional(bool b = true) {
_conditionalFl = b;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,392 @@
/* 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/>.
*
*/
#include "graphics/cursorman.h"
#include "bagel/spacebar/baglib/fmovie.h"
#include "bagel/boflib/string.h"
#include "bagel/boflib/palette.h"
#include "bagel/spacebar/boflib/app.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/spacebar/boflib/std_keys.h"
namespace Bagel {
namespace SpaceBar {
CBagFMovie::CBagFMovie(CBofWindow *parent, const char *filename, CBofRect *bounds, bool useNewPalette, bool blackOutWindow) {
// Allow movie to not shift to new palette.
_useNewPaletteFl = useNewPalette;
// Black out first and last frame of flythroughs and examine movies
_blackOutWindowFl = blackOutWindow;
CBagFMovie::initialize(parent);
CBagFMovie::open(filename, bounds);
}
CBagFMovie::~CBagFMovie() {
CBagFMovie::closeMovie();
}
ErrorCode CBagFMovie::initialize(CBofWindow *pParent) {
// Movie Stuff
_movieStatus = MOVIE_STOPPED;
_escCanStopFl = true;
_smackerPal = nullptr;
_bmpBuf = nullptr;
_filterBmp = nullptr;
_bufferStart = nullptr;
_bufferLength = 0;
// Smacker Stuff
_smk = nullptr;
_loopFl = false;
// Call dialog box creates
if (create("MovieWin", 0, 0, 1, 1, pParent, 1) == ERR_NONE) {
setCapture();
}
return ERR_NONE;
}
bool CBagFMovie::open(const char *filename, CBofRect *bounds) {
// No filename, so put up an open file box
if (filename == nullptr) {
assert(filename);
return false;
}
if (bounds != nullptr) {
_cRect = *bounds;
}
if (openMovie(filename)) {
// We were given specific rect for movie
if (bounds)
reSize(bounds, true);
else
// Center the movie to the parent window
centerRect();
// Paint the image to the screen.
_filterBmp->paint(this, 0, 0);
return true;
}
return false;
}
bool CBagFMovie::openMovie(const char *sFilename) {
assert(sFilename[0] != '\0');
if (_smk) {
closeMovie();
}
_smk = new Video::SmackerDecoder();
_smk->setSoundType(Audio::Mixer::kSFXSoundType);
// Opened failed ?
if (!_smk->loadFile(sFilename)) {
error("Movie not found=%s", sFilename);
}
// Allocate the bitmaps.
_smackerPal = new CBofPalette();
_bmpBuf = new CBofBitmap(_smk->getWidth(), _smk->getHeight(), _smackerPal, false);
_filterBmp = new CBofBitmap(_smk->getWidth(), _smk->getHeight(), _smackerPal, false);
_filterBmp->lock();
selectPalette(_smackerPal);
if (_bmpBuf) {
_bmpBuf->lock();
_bmpBuf->fillRect(nullptr, _smackerPal->getNearestIndex(CTEXT_WHITE));
_bufferStart = (char *)_bmpBuf->getPixelAddress(0, _bmpBuf->isTopDown() ? 0 : (_bmpBuf->height() - 1));
_bufferLength = ABS(_bmpBuf->height() * _bmpBuf->width());
const Graphics::Surface *frame = _smk->decodeNextFrame();
_smackerPal->setData(_smk->getPalette());
if (frame) {
_bmpBuf->getSurface().blitFrom(*frame);
}
}
const bool repaintFl = true;
_bounds = CBofRect(0, 0, (uint16)_bmpBuf->width() - 1, (uint16)_bmpBuf->height() - 1);
reSize(&_bounds, repaintFl);
CBagMasterWin *curWin = CBagel::getBagApp()->getMasterWnd();
if (curWin != nullptr) {
CBagStorageDevWnd *curSDev = curWin->getCurrentStorageDev();
if ((curSDev != nullptr) && curSDev->isFiltered()) {
const uint16 filterId = curSDev->getFilterId();
const FilterFunction filterFunction = curSDev->getFilter();
_bmpBuf->paint(_filterBmp);
(*filterFunction)(filterId, _filterBmp, &_bounds);
}
}
return true;
}
void CBagFMovie::onKeyHit(uint32 keyCode, uint32 /* repCount */) {
if (_escCanStopFl && keyCode == BKEY_ESC) {
// Clean up and exit
_loopFl = false;
stop();
onMovieDone();
}
}
void CBagFMovie::onMainLoop() {
if (!_smk->needsUpdate() || (_movieStatus == MOVIE_STOPPED))
return;
// Smack the current frame into the buffer
const Graphics::Surface *frame = _smk->decodeNextFrame();
if (_smk->hasDirtyPalette()) {
_smackerPal->setData(_smk->getPalette());
}
if (frame) {
_bmpBuf->getSurface().blitFrom(*frame);
}
_bmpBuf->paint1To1(_filterBmp);
// Filter the bitmap.
CBagMasterWin *curWin = CBagel::getBagApp()->getMasterWnd();
if (curWin != nullptr) {
CBagStorageDevWnd *curSDev = curWin->getCurrentStorageDev();
if ((curSDev != nullptr) && curSDev->isFiltered()) {
const uint16 filterId = curSDev->getFilterId();
const FilterFunction filterFunction = curSDev->getFilter();
(*filterFunction)(filterId, _filterBmp, &_bounds);
}
}
// Paint the buffer to the screen.
_filterBmp->paint(this, 0, 0);
if (_movieStatus == MOVIE_FORWARD) {
if (_smk->getCurFrame() == (int)_smk->getFrameCount() - 1) {
if (_loopFl == false) {
onMovieDone();
} else {
seekToStart();
_smk->start();
}
}
} else if (_movieStatus == MOVIE_REVERSE) {
if (_smk->getCurFrame() == 0 || _smk->getCurFrame() == 1) {
if (_loopFl == false) {
onMovieDone();
} else {
seekToEnd();
}
} else {
setFrame(_smk->getCurFrame() - 2); // HACK: Reverse playback
}
}
}
void CBagFMovie::onPaint(CBofRect *) {
}
void CBagFMovie::closeMovie() {
delete _smk;
_smk = nullptr;
if (_filterBmp != nullptr) {
_filterBmp->unlock();
delete _filterBmp;
_filterBmp = nullptr;
}
if (_bmpBuf != nullptr) {
_bmpBuf->unlock();
delete _bmpBuf;
_bmpBuf = nullptr;
}
delete _smackerPal;
_smackerPal = nullptr;
_bufferStart = nullptr;
_bufferLength = 0;
}
void CBagFMovie::onClose() {
closeMovie();
CBofDialog::onClose();
}
void CBagFMovie::onMovieDone() {
if (!_loopFl) {
if (_bCaptured)
releaseCapture();
getParent()->enable();
_bEndDialog = true;
}
}
bool CBagFMovie::play(bool loop, bool escCanStop) {
_escCanStopFl = escCanStop;
_loopFl = loop;
const bool retVal = play();
getParent()->disable();
getParent()->flushAllMessages();
CursorMan.showMouse(false);
doModal();
CursorMan.showMouse(true);
return retVal;
}
bool CBagFMovie::play() {
if (!_smk)
return false;
_smk->pauseVideo(false);
// _smk->setReverse(false); // TODO: Not supported by SMK
_smk->start();
_movieStatus = MOVIE_FORWARD;
return true;
}
bool CBagFMovie::reverse(bool loop, bool escCanStop) {
_escCanStopFl = escCanStop;
_loopFl = loop;
const bool retVal = reverse();
getParent()->disable();
getParent()->flushAllMessages();
doModal();
return retVal;
}
bool CBagFMovie::reverse() {
if (!_smk)
return false;
_smk->pauseVideo(false);
// _smk->setReverse(true); // TODO: Not supported by SMK
_smk->start();
_movieStatus = MOVIE_REVERSE;
return true;
}
bool CBagFMovie::stop() {
if (!_smk)
return false;
_smk->stop();
_movieStatus = MOVIE_STOPPED;
return true;
}
bool CBagFMovie::pause() {
if (!_smk)
return false;
_smk->pauseVideo(true);
_movieStatus = MOVIE_PAUSED;
return true;
}
bool CBagFMovie::seekToStart() {
if (!_smk)
return false;
_smk->rewind();
return true;
}
bool CBagFMovie::seekToEnd() {
if (!_smk)
return false;
setFrame(_smk->getFrameCount() - 2); // HACK: Reverse rewind
return true;
}
uint32 CBagFMovie::getFrame() {
if (_smk) {
return _smk->getCurFrame();
}
return (uint32) -1;
}
bool CBagFMovie::setFrame(uint32 frameNum) {
if (!_smk)
return false;
frameNum = CLIP<uint32>(frameNum, 0, _smk->getFrameCount() - 1);
_smk->forceSeekToFrame(frameNum);
return true;
}
bool CBagFMovie::centerRect() {
CBofRect clientRect = getParent()->getClientRect();
const RECT parentRect = clientRect.getWinRect();
const int clientWidth = parentRect.right - parentRect.left;
const int clientHeight = parentRect.bottom - parentRect.top;
// Get Movies width and height
const int movieWidth = _smk->getWidth();
const int movieHeight = _smk->getHeight();
RECT movieBounds;
movieBounds.left = (clientWidth - movieWidth) / 2;
movieBounds.top = (clientHeight - movieHeight) / 2;
movieBounds.right = movieBounds.left + movieWidth;
movieBounds.bottom = movieBounds.top + movieHeight;
// Reposition the playback window
clientRect = movieBounds;
reSize(&clientRect, true);
return true;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,139 @@
/* 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 BAGEL_BAGLIB_FMOVIE_H
#define BAGEL_BAGLIB_FMOVIE_H
#include "video/smk_decoder.h"
#include "bagel/spacebar/boflib/gui/dialog.h"
#include "bagel/boflib/rect.h"
#include "bagel/boflib/error.h"
#include "bagel/boflib/palette.h"
namespace Bagel {
namespace SpaceBar {
class CBagFMovie : public CBofDialog {
public:
enum MovieStatus {
MOVIE_STOPPED, MOVIE_PAUSED, MOVIE_FORWARD, MOVIE_REVERSE
};
protected:
Video::SmackerDecoder *_smk;
bool _escCanStopFl;
bool _loopFl;
MovieStatus _movieStatus;
CBofBitmap *_bmpBuf;
CBofBitmap *_filterBmp;
CBofPalette *_smackerPal;
char *_bufferStart;
int _bufferLength;
CBofRect _bounds;
bool _useNewPaletteFl;
bool _blackOutWindowFl;
/**
* Open the movie file, center it in parent, rewind it, and realize it's
* palette in the background
*/
virtual ErrorCode initialize(CBofWindow *pParent);
/**
* Open the movie file, center it in parent, rewind it, and realize it's
* palette in the background.
*/
virtual bool openMovie(const char *sFilename);
/**
* Close the MCI Device file
*/
virtual void closeMovie();
void onReSize(CBofSize *pSize) override {
};
virtual bool play();
virtual bool reverse();
void onLButtonUp(uint32 flags, CBofPoint *point, void * = nullptr) override {
onButtonUp(flags, point);
}
virtual void onButtonUp(uint32 flags, CBofPoint *point) {
};
void onPaint(CBofRect *pRect) override;
virtual void onMovieDone();
void onClose() override;
void onMainLoop() override;
/**
* Catch the ESC key when hit
*/
void onKeyHit(uint32 keyCode, uint32 repCount) override;
public:
/**
* Initializes Movie Object and opens movie file @ Rect
* @param parent A pointer to the parent window
* @param filename String containing filename of movie to be opened
* @param bounds Location for video object relative to parent
* @param useNewPalette
* @param blackOutWindow
*/
CBagFMovie(CBofWindow *parent = nullptr, const char *filename = nullptr,
CBofRect *bounds = nullptr, bool useNewPalette = true, bool blackOutWindow = false);
/**
* Destructor
*/
~CBagFMovie();
/**
* Open the movie file, place it @ bounds, rewind it, and realize it's
* palette in the background.
*/
virtual bool open(const char *filename = nullptr, CBofRect *bounds = nullptr);
virtual bool play(bool loop, bool escCanStop = true);
virtual bool reverse(bool loop, bool escCanStop = true);
virtual bool pause();
virtual bool stop();
virtual MovieStatus status() {
return _movieStatus;
}
virtual bool seekToStart();
virtual bool seekToEnd();
virtual uint32 getFrame();
virtual bool setFrame(uint32 frameNum);
virtual bool centerRect();
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,274 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/help.h"
#include "bagel/spacebar/boflib/file.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/log.h"
#include "bagel/spacebar/boflib/std_keys.h"
namespace Bagel {
namespace SpaceBar {
#define RULES_DIR "$SBARDIR\\GENERAL\\RULES\\"
#define HELP_OK_X 257
#define HELP_OK_Y 377
#define HELP_OK_CX 125
#define HELP_OK_CY 30
#define HELP_OK_UP "DONE1.BMP"
#define HELP_OK_DOWN "DONE2.BMP"
#define HELP_OK_FOCUS "DONE3.BMP"
#define HELP_OK_DISABLED "DONE4.BMP"
#define HELP_OK_ID 1
#define HELP_PAGE_UP_X 81
#define HELP_PAGE_UP_Y 377
#define HELP_PAGE_UP_CX 125
#define HELP_PAGE_UP_CY 30
#define HELP_PAGE_UP_UP "PAGEUP1.BMP"
#define HELP_PAGE_UP_DOWN "PAGEUP2.BMP"
#define HELP_PAGE_UP_FOCUS "PAGEUP3.BMP"
#define HELP_PAGE_UP_DISABLED "PAGEUP4.BMP"
#define HELP_PAGE_UP_ID 2
#define HELP_PAGE_DOWN_X 435
#define HELP_PAGE_DOWN_Y 377
#define HELP_PAGE_DOWN_CX 125
#define HELP_PAGE_DOWN_CY 30
#define HELP_PAGE_DOWN_UP "PAGEDN1.BMP"
#define HELP_PAGE_DOWN_DOWN "PAGEDN2.BMP"
#define HELP_PAGE_DOWN_FOCUS "PAGEDN3.BMP"
#define HELP_PAGE_DOWN_DISABLED "PAGEDN4.BMP"
#define HELP_PAGE_DOWN_ID 3
// Local functions
const char *buildHelpDir(const char *fileName);
CBagHelp::CBagHelp() {
_textBox = nullptr;
_okButton = nullptr;
_pageUp = nullptr;
_pageDown = nullptr;
_savePalette = nullptr;
setFlags(0);
}
ErrorCode CBagHelp::attach() {
assert(isValidObject(this));
// Save off the current game's palette
_savePalette = CBofApp::getApp()->getPalette();
// Insert ours
CBofPalette *backPal = _pBackdrop->getPalette();
CBofApp::getApp()->setPalette(backPal);
_okButton = new CBofBmpButton;
CBofBitmap *upBmp = loadBitmap(buildHelpDir(HELP_OK_UP), backPal);
CBofBitmap *downBmp = loadBitmap(buildHelpDir(HELP_OK_DOWN), backPal);
CBofBitmap *focusBmp = loadBitmap(buildHelpDir(HELP_OK_FOCUS), backPal);
CBofBitmap *disableBmp = loadBitmap(buildHelpDir(HELP_OK_DISABLED), backPal);
_okButton->loadBitmaps(upBmp, downBmp, focusBmp, disableBmp);
_okButton->create("OK", HELP_OK_X, HELP_OK_Y, HELP_OK_CX, HELP_OK_CY, this, HELP_OK_ID);
_okButton->show();
_pageUp = new CBofBmpButton;
upBmp = loadBitmap(buildHelpDir(HELP_PAGE_UP_UP), backPal);
downBmp = loadBitmap(buildHelpDir(HELP_PAGE_UP_DOWN), backPal);
focusBmp = loadBitmap(buildHelpDir(HELP_PAGE_UP_FOCUS), backPal);
disableBmp = loadBitmap(buildHelpDir(HELP_PAGE_UP_DISABLED), backPal);
_pageUp->loadBitmaps(upBmp, downBmp, focusBmp, disableBmp);
_pageUp->create("PageUp", HELP_PAGE_UP_X, HELP_PAGE_UP_Y, HELP_PAGE_UP_CX, HELP_PAGE_UP_CY, this, HELP_PAGE_UP_ID);
_pageUp->show();
_pageDown = new CBofBmpButton;
upBmp = loadBitmap(buildHelpDir(HELP_PAGE_DOWN_UP), backPal);
downBmp = loadBitmap(buildHelpDir(HELP_PAGE_DOWN_DOWN), backPal);
focusBmp = loadBitmap(buildHelpDir(HELP_PAGE_DOWN_FOCUS), backPal);
disableBmp = loadBitmap(buildHelpDir(HELP_PAGE_DOWN_DISABLED), backPal);
_pageDown->loadBitmaps(upBmp, downBmp, focusBmp, disableBmp);
_pageDown->create("PageDown", HELP_PAGE_DOWN_X, HELP_PAGE_DOWN_Y, HELP_PAGE_DOWN_CX, HELP_PAGE_DOWN_CY, this, HELP_PAGE_DOWN_ID);
_pageDown->show();
CBofFile file(_textFile, CBF_BINARY | CBF_READONLY);
const uint32 size = file.getLength();
char *buffer = (char *)bofCleanAlloc(size + 1);
file.read(buffer, size);
CBofRect cRect;
cRect.setRect(120, 100, 550, 348);
_textBox = new CBofTextBox(this, &cRect, buffer);
_textBox->setPageLength(18);
bofFree(buffer);
CBagCursor::showSystemCursor();
return _errCode;
}
ErrorCode CBagHelp::detach() {
assert(isValidObject(this));
CBagCursor::hideSystemCursor();
delete _textBox;
_textBox = nullptr;
delete _pageDown;
_pageDown = nullptr;
delete _pageUp;
_pageUp = nullptr;
delete _okButton;
_okButton = nullptr;
CBofApp::getApp()->setPalette(_savePalette);
return _errCode;
}
ErrorCode CBagHelp::SetHelpFile(const char *textFile) {
assert(isValidObject(this));
assert(textFile != nullptr);
_textFile = textFile;
return _errCode;
}
void CBagHelp::onPaint(CBofRect *rect) {
assert(isValidObject(this));
paintBackdrop(rect);
if (_textBox != nullptr) {
_textBox->display();
}
validateAnscestors();
}
void CBagHelp::onKeyHit(uint32 keyCode, uint32 repCount) {
assert(isValidObject(this));
switch (keyCode) {
case BKEY_UP:
if (_textBox != nullptr) {
_textBox->lineUp();
}
break;
case BKEY_DOWN:
if (_textBox != nullptr) {
_textBox->lineDown();
}
break;
case BKEY_PAGEUP:
if (_textBox != nullptr) {
_textBox->pageUp();
}
break;
case BKEY_PAGEDOWN:
if (_textBox != nullptr) {
_textBox->pageDown();
}
break;
case BKEY_ESC:
case BKEY_ENTER:
close();
// FIXME: missing break?
// fallthrough
default:
CBofDialog::onKeyHit(keyCode, repCount);
break;
}
}
void CBagHelp::onBofButton(CBofObject *object, int flags) {
assert(isValidObject(this));
assert(object != nullptr);
if (flags != BUTTON_CLICKED)
return;
CBofBmpButton *pButton = (CBofBmpButton *)object;
switch (pButton->getControlID()) {
case HELP_OK_ID:
close();
break;
case HELP_PAGE_UP_ID:
if (_textBox != nullptr) {
_textBox->pageUp();
}
break;
case HELP_PAGE_DOWN_ID:
if (_textBox != nullptr) {
_textBox->pageDown();
}
break;
default:
logWarning("Unknown button");
break;
}
}
const char *buildHelpDir(const char *fileName) {
return formPath(RULES_DIR, fileName);
}
void CBagHelp::onInitDialog() {
assert(isValidObject(this));
CBofDialog::onInitDialog();
attach();
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,61 @@
/* 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 BAGEL_BAGLIB_HELP_H
#define BAGEL_BAGLIB_HELP_H
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/boflib/gui/text_box.h"
#include "bagel/spacebar/boflib/gui/button.h"
#include "bagel/boflib/string.h"
namespace Bagel {
namespace SpaceBar {
class CBagHelp : public CBofDialog {
public:
CBagHelp();
virtual ErrorCode attach();
virtual ErrorCode detach();
void onInitDialog() override;
ErrorCode SetHelpFile(const char *textFile);
protected:
void onPaint(CBofRect *rect) override;
void onBofButton(CBofObject *object, int state) override;
void onKeyHit(uint32 keyCode, uint32 repCount) override;
CBofString _textFile;
CBofTextBox *_textBox;
CBofBmpButton *_okButton;
CBofBmpButton *_pageUp;
CBofBmpButton *_pageDown;
CBofPalette *_savePalette;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,112 @@
/* 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/>.
*
*/
#include "common/util.h"
#include "bagel/spacebar/baglib/ifstream.h"
#include "bagel/boflib/stdinc.h"
namespace Bagel {
namespace SpaceBar {
CBagIfstream::CBagIfstream(char *buffer, int length) {
_currPtr = _buffer = buffer;
_eof = buffer + length;
_length = length;
_lineNumber = 1;
_lineString = "";
}
int CBagIfstream::getCh() {
const int ch = get();
return ch;
}
int CBagIfstream::getLine(char *buffer, int length) {
return get(buffer, length, '\n');
}
void CBagIfstream::putBack() {
if (_currPtr > _buffer)
_currPtr--;
}
int CBagIfstream::get() {
if (_currPtr != _eof)
return *_currPtr++;
return -1;
}
int CBagIfstream::get(char *buffer, int count, char delimiter) {
if (!eof()) {
count = MIN<int>(count, _eof - _currPtr);
char *p = (char *)memchr(_currPtr, delimiter, count);
if (p != nullptr) {
count = MIN<int>(count, p - _currPtr /* + 1*/);
}
memcpy(buffer, _currPtr, count);
_currPtr += count;
assert(_currPtr <= _eof);
return _currPtr == _eof ? -1 : 0;
}
return -1;
}
int CBagIfstream::peek() {
if (_currPtr != _eof)
return *_currPtr;
return -1;
}
int CBagIfstream::getCh(char *ch, int count, char delimiter) {
get(ch, count, delimiter);
if (delimiter == '\n') {
_lineNumber++;
_lineString = "";
}
return 0;
}
bool CBagIfstream::eatWhite() {
int ch = peek();
while ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n')) {
if (ch == '\n') {
_lineNumber++;
_lineString = "";
}
getCh();
ch = peek();
}
return (ch != -1);
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,72 @@
/* 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 BAGEL_BAGLIB_IFSTREAM_H
#define BAGEL_BAGLIB_IFSTREAM_H
#include "bagel/boflib/object.h"
#include "bagel/boflib/string.h"
namespace Bagel {
namespace SpaceBar {
class CBagIfstream : public CBofObject {
private:
int _lineNumber;
CBofString _lineString;
char *_buffer;
char *_currPtr;
char *_eof;
int _length;
public:
CBagIfstream(char *buffer, int length);
virtual ~CBagIfstream() {}
int getCh();
int getLine(char *buffer, int length);
void putBack();
int get();
int get(char *buffer, int count, char delimiter = '\n');
int peek();
int getCh(char *ch, int count, char delimiter = '\n');
bool eatWhite();
bool eof() const {
return (_currPtr == _eof);
}
int getLineNumber() const {
return _lineNumber;
}
int getSize() const {
return _length;
}
const CBofString &getLineString() const {
return _lineString;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,119 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/inv.h"
#include "bagel/spacebar/baglib/character_object.h"
#include "bagel/spacebar/baglib/movie_object.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/zoom_pda.h"
#include "bagel/spacebar/baglib/pda.h"
namespace Bagel {
namespace SpaceBar {
#define FIRS_STASH_MOV "FIRST_STASH_MOVIE"
bool CBagInv::_firstStashFl;
//
// This is called when a object is inserted into the inventory
// The wand on the PDA should animate
//
ErrorCode CBagInv::activateLocalObject(const CBofString &objectName) {
CBagStorageDev *pdaSDev = g_SDevManager->getStorageDevice("BPDA_WLD");
// Don't do any wand animation if we are zoomed.
SBZoomPda *zoomPda = (SBZoomPda *)g_SDevManager->getStorageDevice("BPDAZ_WLD");
assert(zoomPda != nullptr);
const bool zoomedFl = (zoomPda ? zoomPda->getZoomed() : false);
if (pdaSDev && zoomedFl == false) {
CBagCharacterObject *wand = (CBagCharacterObject *)pdaSDev->getObject("WANDANIM");
CBagPDA *pda = (CBagPDA *)pdaSDev;
if (wand) {
wand->setPlaybackSpeed(1);
wand->setNumOfLoops(1);
// Let our character anim know that this is our PDA Wand,
// it will need to let the pda update code know that
// it needs to get redrawn.
CBagCharacterObject::setPdaWand(wand);
pda->setDirty(true);
}
}
if (zoomedFl == false) {
// Check to see if we are in the bar
CBagVar *var = g_VarManager->getVariable("INBAR");
if (var != nullptr) {
var = g_VarManager->getVariable("FIRST_STASH");
// If this is our first stash, play the smacker associated with it.
if ((var != nullptr) && (var->getNumValue() == 0)) {
CBagMovieObject *pMovie = (CBagMovieObject *)getObject(FIRS_STASH_MOV);
if (pMovie) {
if (pMovie->isAttached() == false) {
pMovie->attach();
pMovie->setVisible();
}
pMovie->runObject();
}
var->setValue(1);
}
}
}
return CBagStorageDevBmp::activateLocalObject(objectName);
}
/**
* This is called when a object is removed from the inventory
* The wand on the PDA should animate
*/
ErrorCode CBagInv::deactivateLocalObject(const CBofString &objectName) {
CBagStorageDev *pdaSDev = g_SDevManager->getStorageDevice("BPDA_WLD");
// Don't do any wand animation if we are zoomed.
SBZoomPda *zoomPDA = (SBZoomPda *)g_SDevManager->getStorageDevice("BPDAZ_WLD");
assert(zoomPDA != nullptr);
const bool zoomedFl = (zoomPDA ? zoomPDA->getZoomed() : false);
if (pdaSDev && zoomedFl == false) {
CBagCharacterObject *wand = (CBagCharacterObject *)pdaSDev->getObject("WANDANIM");
if (wand) {
wand->setPlaybackSpeed(-1);
wand->setNumOfLoops(1);
// Let it know our ending frame is 0, not 1.
wand->setEndFrame(0);
}
}
return CBagStorageDevBmp::deactivateLocalObject(objectName);;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,51 @@
/* 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 BAGEL_BAGLIB_INV_H
#define BAGEL_BAGLIB_INV_H
#include "bagel/spacebar/baglib/storage_dev_bmp.h"
namespace Bagel {
namespace SpaceBar {
class CBagInv : public CBagStorageDevBmp {
protected:
static bool _firstStashFl;
public:
CBagInv() : CBagStorageDevBmp() {
}
virtual ~CBagInv() {
}
static void initialize() {
_firstStashFl = true;
}
ErrorCode activateLocalObject(const CBofString &objectName) override;
ErrorCode deactivateLocalObject(const CBofString &objectName) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,209 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/link_object.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
namespace Bagel {
namespace SpaceBar {
extern bool g_noMenuFl;
CBagLinkObject::CBagLinkObject() {
_xObjType = LINK_OBJ;
_linkType = LINK;
_destLocation = CBofPoint(0, 0);
_srcLocation = CBofPoint(-1, -1);
_fade = 0;
setVisible(false);
CBagObject::setOverCursor(5);
}
CBagLinkObject::~CBagLinkObject() {
CBagObject::detach();
}
CBofRect CBagLinkObject::getRect() {
const CBofPoint p = getPosition();
const CBofSize s = getSize();
CBofRect r = CBofRect(p, s);
return r;
}
ParseCodes CBagLinkObject::setInfo(CBagIfstream &istr) {
bool objectUpdatedFl = false;
ParseCodes returnCode = PARSING_DONE;
bool doneFl = false;
while (!doneFl && !istr.eof()) {
const char ch = (char)istr.peek();
switch (ch) {
//
// @[x,y] - destination of a flythru. start point in next world
//
case '@': {
CBofRect r;
istr.getCh();
getRectFromStream(istr, r);
setDstLoc(r.topLeft());
objectUpdatedFl = true;
break;
}
//
// #[x,y] - start location of a flythru. start point in this world
//
case '#': {
CBofRect r;
istr.getCh();
getRectFromStream(istr, r);
setSrcLoc(r.topLeft());
objectUpdatedFl = true;
break;
}
//
// AS [LINK|CLOSEUP] - how to run the link
//
case 'A': {
char localBuffer[256];
localBuffer[0] = 0;
CBofString curString(localBuffer, 256);
getAlphaNumFromStream(istr, curString);
if (!curString.find("AS")) {
istr.eatWhite();
getAlphaNumFromStream(istr, curString);
if (!curString.find("CLOSEUP")) {
_linkType = CLOSEUP;
setOverCursor(2);
objectUpdatedFl = true;
} else if (!curString.find("LINK")) {
_linkType = LINK;
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, curString);
putbackStringOnStream(istr, "AS ");
}
} else {
putbackStringOnStream(istr, curString);
}
break;
}
//
// FADE n
//
case 'F': {
char localBuffer[256];
localBuffer[0] = 0;
CBofString curString(localBuffer, 256);
getAlphaNumFromStream(istr, curString);
if (!curString.find("FADE")) {
istr.eatWhite();
getIntFromStream(istr, _fade);
objectUpdatedFl = true;
} else {
putbackStringOnStream(istr, curString);
}
break;
}
//
// No match return from function
//
default: {
const ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
returnCode = PARSING_DONE;
doneFl = true;
} else if (parseCode == UPDATED_OBJECT) {
objectUpdatedFl = true;
} else { // rc==UNKNOWN_TOKEN
if (objectUpdatedFl)
returnCode = UPDATED_OBJECT;
else
returnCode = UNKNOWN_TOKEN;
doneFl = true;
}
break;
}
}
}
return returnCode;
}
bool CBagLinkObject::runObject() {
// Reset Wield
g_noMenuFl = false;
char buffer[256];
buffer[0] = '\0';
CBofString curStr(buffer, 256);
curStr = getFileName();
// If this is a special link (using the last known sdev stack),
// then find it's value, and use that instead.
if (getFileName().find("$LASTWORLD") != -1) {
curStr = getFileName();
CBagVar *var = g_VarManager->getVariable("$LASTWORLD");
if (var != nullptr) {
curStr.replaceStr("$LASTWORLD", var->getValue());
}
}
CBagMasterWin::setActiveCursor(6);
CBagStorageDevWnd *curSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
// Set the link position for the storage device we are about to jump to
CBagStorageDev *destWin = g_SDevManager->getStorageDevice(curStr);
if (destWin) {
destWin->setloadFilePos(getDestLoc());
}
CBagMasterWin *pMasterWin = CBagel::getBagApp()->getMasterWnd();
if (pMasterWin) {
pMasterWin->setCurrfadeIn(_fade);
pMasterWin->setStorageDev(curStr);
}
CBagStorageDevWnd *otherSDev = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if (!curSDev->isCloseup() && !otherSDev->isCloseup()) {
g_VarManager->incrementTimers();
}
return CBagObject::runObject();
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,82 @@
/* 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 BAGEL_BAGLIB_LINK_OBJECT_H
#define BAGEL_BAGLIB_LINK_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagLinkObject is an object that can be place within the slide window.
*/
class CBagLinkObject : public CBagObject {
public:
enum LinkType {
LINK = 0, CLOSEUP = 1
};
private:
CBofSize _size;
CBofPoint _destLocation;
CBofPoint _srcLocation;
LinkType _linkType;
int _fade;
public:
CBagLinkObject();
virtual ~CBagLinkObject();
// Return UPDATED_OBJECT if the Object had members that are properly initialized/de-initialized
ParseCodes setInfo(CBagIfstream &istr) override;
bool runObject() override;
CBofRect getRect() override;
CBofSize getSize() const {
return _size;
}
CBofPoint getDestLoc() const {
return _destLocation;
}
CBofPoint getSrcLoc() const {
return _srcLocation;
}
void setSize(const CBofSize &size) override {
_size = size;
}
void setDstLoc(const CBofPoint &loc) {
_destLocation = loc;
}
void setSrcLoc(const CBofPoint &loc) {
_srcLocation = loc;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,261 @@
/* 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 BAGEL_BAGLIB_LOG_MSG_H
#define BAGEL_BAGLIB_LOG_MSG_H
#include "bagel/spacebar/baglib/text_object.h"
#include "bagel/spacebar/baglib/storage_dev_bmp.h"
namespace Bagel {
namespace SpaceBar {
class CBagLogResidue : public CBagTextObject {
protected:
int _sdevWidth;
public:
CBagLogResidue(int sdevWidth);
virtual ~CBagLogResidue() {
}
void setSize(const CBofSize &size) override;
ErrorCode update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect = nullptr, int maskColor = -1) override;
};
#define MSG_TIME_MASK 0x3FFF
#define MSG_PLAYED_MASK 0x4000
class CBagLogMsg : public CBagTextObject {
protected:
CBofString _msgSendee;
CBofString _msgTimeStr;
int _sdevWidth;
public:
CBagLogMsg(int sdevWidth);
virtual ~CBagLogMsg() {
}
ErrorCode update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect = nullptr, int maskColor = -1) override;
/**
* Takes in info and then removes the relative information and returns the info
* without the relevant info.
*/
ParseCodes setInfo(CBagIfstream &istr) override;
void setSize(const CBofSize &size) override;
void setProperty(const CBofString &prop, int val) override;
int getProperty(const CBofString &prop) override;
void setMsgSendee(const CBofString &sendee) {
_msgSendee = sendee;
}
CBofString getMsgSendee() const {
return _msgSendee;
}
void setMsgTime(int &msgTime) {
const int state = getState();
setState((state & MSG_PLAYED_MASK) | (msgTime & MSG_TIME_MASK));
}
int getMsgTime() {
return getState() & MSG_TIME_MASK;
}
void setMsgPlayed(bool playedFl) {
const int state = getState();
setState((state & MSG_TIME_MASK) | (playedFl == true ? MSG_PLAYED_MASK : 0));
}
bool getMsgPlayed() {
return (getState() & MSG_PLAYED_MASK) != 0;
}
};
#define mSusChecked 0x0001
#define mSusVoicePrinted 0x0002
#define mSusResiduePrinted 0x0004
class CBagLogSuspect : public CBagTextObject {
protected:
int _nSdevWidth;
CBofString _susName;
CBofString _susSpecies;
CBofString _susRoom;
public:
CBagLogSuspect(int sdevWidth);
virtual ~CBagLogSuspect() {
}
ErrorCode update(CBofBitmap *bmp, CBofPoint pt, CBofRect *srcRect = nullptr, int maskColor = -1) override;
void setSize(const CBofSize &size) override;
ParseCodes setInfo(CBagIfstream &istr) override;
void setProperty(const CBofString &prop, int val) override;
int getProperty(const CBofString &prop) override;
void setSusName(const CBofString &susName) {
_susName = susName;
}
void setSusSpecies(const CBofString &susSpecies) {
_susSpecies = susSpecies;
}
void setSusRoom(const CBofString &susRoom) {
_susRoom = susRoom;
}
void setSusVoicePrinted(bool bVal) {
bVal == false ? setState(getState() & ~mSusVoicePrinted) : setState(getState() | mSusVoicePrinted);
}
bool getSusVoicePrinted() {
return (getState() & mSusVoicePrinted) != 0;
}
void setSusResiduePrinted(bool bVal) {
bVal == false ? setState(getState() & ~mSusResiduePrinted) : setState(getState() | mSusResiduePrinted);
}
bool getSusResiduePrinted() {
return (getState() & mSusResiduePrinted) != 0;
}
void setSusChecked(bool bVal) {
bVal == false ? setState(getState() & ~mSusChecked) : setState(getState() | mSusChecked);
}
bool getSusChecked() {
return (getState() & mSusChecked) != 0;
}
};
class CBagLog : public CBagStorageDevBmp {
protected:
// Queued messages waited to be played and inserted into SDEV
CBofList<CBagObject *> *_queuedMsgList;
static CBagLog *_lastFloatPage;
public:
CBagLog();
virtual ~CBagLog();
static void initialize() {
_lastFloatPage = nullptr;
}
CBagObject *onNewUserObject(const CBofString &initStr) override;
/**
* This is different for the log sdev Object are just queued for insertion
* and the message light starts blinking. The messages will be added
* to the sdev when the message light is clicked
* @return Error result code
*/
ErrorCode activateLocalObject(CBagObject *bagObj) override;
/**
* Releases and deletes all the objects in the list
*/
ErrorCode releaseMsg();
ErrorCode playMsgQueue();
/**
* Remove a (duplicate) message from the message queue
*/
bool removeFromMsgQueue(CBagObject *bagObj);
/**
* This function arranges the objects that are considered floating
* (no coordinates given in script). It is virtual so that derived
* storage devices can do special things, like paging etc.
* @return Returns the next available location in the sdev,
* at this level the objects will go out of range of the sdev.
*/
CBofPoint arrangeFloater(CBofPoint &pos, CBagObject *bagObj) override;
int getCurFltPage();
void setCurFltPage(int fltPage);
static void arrangePages();
static void initArrangePages() {
_lastFloatPage = nullptr;
}
};
class CBagEnergyDetectorObject : public CBagTextObject {
public:
CBagEnergyDetectorObject();
virtual ~CBagEnergyDetectorObject();
// Need private setinfo so we can parse energy detector fields
ParseCodes setInfo(CBagIfstream &istr) override;
ErrorCode update(CBofBitmap *, CBofPoint, CBofRect *, int) override;
ErrorCode attach() override;
void setMsgTime(int &nVal) {
setState(nVal);
}
int getMsgTime() {
return getState();
}
private:
CBofString _energyTimeStr;
CBofString _zhapsStr;
CBofString _causeStr;
bool _textInitializedFl;
};
// Special object, clue object.
class CBagLogClue : public CBagTextObject {
private:
CBagVar *_stringVar1;
CBagVar *_stringVar2;
CBagVar *_stringVar3;
CBagVar *_stringVar4;
int _sdevWidth;
public:
CBagLogClue(const CBofString &initStr, int sdevWidth, int pointSize);
virtual ~CBagLogClue() {
}
ErrorCode attach() override;
ParseCodes setInfo(CBagIfstream &istr) override;
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *srcRect = nullptr, int maskColor = -1) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,214 @@
/* 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 BAGEL_BAGLIB_MASTER_WIN_H
#define BAGEL_BAGLIB_MASTER_WIN_H
#include "bagel/spacebar/boflib/gfx/text.h"
#include "bagel/spacebar/baglib/cursor.h"
#include "bagel/boflib/string.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/boflib/gui/window.h"
#include "bagel/boflib/sound.h"
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/baglib/save_game_file.h"
#include "bagel/spacebar/baglib/var.h"
namespace Bagel {
namespace SpaceBar {
#define g_SDevManager CBagel::getBagApp()->getMasterWnd()->getStorageDevManager()
#define g_VarManager CBagel::getBagApp()->getMasterWnd()->getVariableManager()
class CBagStorageDevManager;
class CBagStorageDevWnd;
class CBagStorageDev;
enum SpaceBarEventType {
WM_ENTER_PAN_WINDOW = 1001,
WM_ENTER_CLOSE_UP_WINDOW = 1002,
WM_EXIT_CLOSE_UP_WINDOW = 1003,
WM_ENTER_NEW_WLD = 1004,
WM_DIE = 1005,
WM_SHOW_SYSTEM_DLG = 1006
};
#define MAX_CURSORS 60
// Some utility routines
void setCICStatus(CBagStorageDev *sdev);
bool getCICStatus();
/**
* This is the main window that is never destroyed throughout the game.
* It handles bringing new windows in and out of focus as well as
* containing the parsing file and info. It also captures
* keyboard entry and will save state information
*/
class CBagMasterWin : public CBofWindow, public CBagParseObject {
protected:
static bool _objSaveFl;
static StObj *_objList;
static CBagCursor *_cursorList[MAX_CURSORS];
CBagStorageDevWnd *_gameWindow;
CBofString _wldScript;
CBofString _startWld;
CBofString _cdChangeAudio;
CBofString _sysScreen;
uint16 _diskId;
int _fadeIn;
CBofList<CBagStorageDev *> *_gameSDevList;
CBagStorageDevManager *_storageDeviceList;
CBagVarManager *_variableList; // List of variables used throughout wld
CBofSound *_waitSound;
static int _curCursor;
public:
static int _menuCount;
CBagMasterWin();
virtual ~CBagMasterWin();
virtual ErrorCode Run();
ErrorCode close() override;
CBofString &getWldScript() {
return _wldScript;
}
static void setActiveCursor(int cursorId);
static int getActiveCursor() {
return _curCursor;
}
// User options
static bool getFlyThru();
static bool getPanimations();
static void setPanimations(bool panimsFl);
static int getCorrection();
static void setCorrection(int correction);
static int getPanSpeed();
static void setPanSpeed(int speed);
static int getMidiVolume();
static void setMidiVolume(int vol);
static int getWaveVolume();
static void setWaveVolume(int vol);
static bool getMidi() {
return getMidiVolume() != 0;
}
static bool getDigitalAudio() {
return getWaveVolume() != 0;
}
static void muteToggle();
static void forcePaintScreen();
virtual ErrorCode showSystemDialog(bool saveFl = true);
bool showRestartDialog(CBofWindow *win = nullptr, bool saveFl = true);
bool showSaveDialog(CBofWindow *win, bool saveFl = true);
bool showRestoreDialog(CBofWindow *win, bool saveFl = true);
bool showQuitDialog(CBofWindow *win, bool saveFl = true);
ErrorCode showCreditsDialog(CBofWindow *win, bool saveFl = true);
void fillSaveBuffer(StBagelSave *saveBuf);
void doRestore(StBagelSave *saveBuf);
ErrorCode newGame();
ErrorCode loadFile(const CBofString &wldName, const CBofString &startWldName, bool restartFl = false, bool setStartFl = true);
ErrorCode loadFileFromStream(CBagIfstream &input, const CBofString &wldName);
ErrorCode loadGlobalVars(const CBofString &wldName);
ErrorCode setCurrfadeIn(int fade) {
_fadeIn = fade;
return ERR_NONE;
}
ErrorCode setStorageDev(const CBofString &wldName, bool entry = true);
ErrorCode gotoNewWindow(const CBofString *str);
uint16 getDiskID() const {
return _diskId;
}
void setDiskID(uint16 id) {
_diskId = id;
}
CBofWindow *getCurrentGameWindow() const {
return (CBofWindow *)_gameWindow;
}
CBagStorageDevWnd *getCurrentStorageDev() const {
return _gameWindow;
}
CBagStorageDevManager *getStorageDevManager() const {
return _storageDeviceList;
}
CBagVarManager *getVariableManager() const {
return _variableList;
}
virtual CBagStorageDev *onNewStorageDev(const CBofString &typestr) = 0;
virtual CBagStorageDev *onNewStorageDev(int type) = 0;
virtual void onNewFilter(CBagStorageDev *, const CBofString &typeStr) = 0;
virtual void onNewFilter(CBagStorageDev *sdev, int type) = 0;
virtual ErrorCode onHelp(const CBofString &helpFile, bool saveBkgFl = true, CBofWindow *parent = nullptr);
void onUserMessage(uint32 message, uint32 param) override;
void onKeyHit(uint32 keyCode, uint32 repCount) override;
void onClose() override;
StObj *getObjList() {
return _objList;
}
void setSaveObjs(bool saveFl) {
_objSaveFl = saveFl;
}
bool isObjSave() {
return _objSaveFl;
}
void saveSDevStack();
// Since we do this from load file and do restore, centralize it in one location.
void restoreActiveMessages(CBagStorageDevManager *sdevManager);
};
ErrorCode waitForInput();
extern bool g_waitOKFl;
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,692 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/menu_dlg.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/spacebar/baglib/text_object.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/zoom_pda.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/log.h"
namespace Bagel {
namespace SpaceBar {
#define MENU_DFLT_HEIGHT 20
#define TIMER_CLOSE_ID 108
#define TIMER_HACK_ID 109
#define DELAY_DEFAULT 0
CBagObject *CBagMenuDlg::_pSelectedObject;
CBofList<CBagObject *> *CBagMenu::_pUniversalObjectList; // Objects used in every menu
int CBagMenu::_nDefaultDelay;
bool g_pauseTimerFl = false;
extern bool g_bAAOk;
#define EXAMINEBMP "$SBARDIR\\GENERAL\\MENUS\\EXAMINE.BMP"
void CBagMenuDlg::initialize() {
_pSelectedObject = nullptr;
}
void CBagMenu::initialize() {
_pUniversalObjectList = nullptr;
_nDefaultDelay = DELAY_DEFAULT;
}
CBagMenu::CBagMenu() {
_nY = 0;
static bool bFirstTime = true;
// Get option for delay for caption boxes
if (bFirstTime) {
bFirstTime = false;
_nDefaultDelay = DELAY_DEFAULT;
CBagel *pBagel = (CBagel *)CBagel::getApp();
if (pBagel != nullptr) {
pBagel->getOption("UserOptions", "TextDelay", &_nDefaultDelay, DELAY_DEFAULT);
if (_nDefaultDelay < 0) {
_nDefaultDelay = -1;
} else if (_nDefaultDelay > 0x7FFF) {
_nDefaultDelay = 0x7FFF;
}
}
}
_nDelay = (int16)_nDefaultDelay;
}
CBagObject *CBagMenu::onNewSpriteObject(const CBofString &) {
CBagSpriteObject *pObj = new CBagSpriteObject();
const CBofPoint pt(0, _nY);
pObj->setPosition(pt);
pObj->setTransparent(false);
return pObj;
}
bool CBagMenu::trackPopupMenu(uint32 /*nFlags*/, int x, int y, CBofWindow *pWnd, CBofPalette * /*pPal*/, CBofRect * /*lpRect*/) {
static int nNumCalls = 0;
CBagMenuDlg dlg;
CBagObject *pObj;
int nObjectPal = -1;
int nMenuCount = 0, nRunItems = 0, nBaseMenuLocX = 3;
CBofList<CBagObject *> xObjList;
int nNumItems = 0;
CBofRect wndRect(80, 10, 80 + 480 - 1, 10 + 360 - 1);
CBofRect objSize;
CBofSize cWieldMenuSize;
CBofSize menuSize(1, 1);
CBofPoint menuLoc(4, 1);
bool bTextOnly = true;
int tmpVal = 0;
CBofPoint cMouseDown(x, y);
bool bZoomed = false;
nNumCalls++;
bool bReturn = true;
CBofWindow *pParent = pWnd;
int nNumWieldChoices = 0;
if ((getObjectList()->getCount() == 1) && (getObjectList()->getTail()->getNodeItem()->getType() == TEXT_OBJ) && (((CBagTextObject *)getObjectList()->getTail()->getNodeItem())->isCaption())) {
nBaseMenuLocX = 0;
} else if (nNumCalls == 1 && _pUniversalObjectList && _pUniversalObjectList != getObjectList()) {
for (int i = 0; i < _pUniversalObjectList->getCount(); ++i) {
pObj = _pUniversalObjectList->getNodeItem(i);
if (pObj->isLocal() && (!pObj->getExpression() || pObj->getExpression()->evaluate(pObj->isNegative()))) {
// Only attach if not attached
if (pObj->isAttached() == false) {
pObj->attach();
// Otherwise, we need to re-calculate the size of the text object,
// since we are gonna trash is with our own values soon.
} else if (pObj->getType() == TEXT_OBJ) {
((CBagTextObject *)pObj)->recalcTextRect(((CBagTextObject *)pObj)->isCaption());
}
if (!pObj->isImmediateRun()) {
// Get the next menu items pos
objSize = pObj->getRect();
if (menuSize.cx < (objSize.width() + menuLoc.x))
menuSize.cx = (objSize.width() + menuLoc.x);
if (menuSize.cy < (objSize.height() + menuLoc.y))
menuSize.cy = (objSize.height() + menuLoc.y);
pObj->setPosition(menuLoc);
pObj->setHighlight(false);
if (!nMenuCount && (pObj->getType() == TEXT_OBJ)) {
menuLoc.y += objSize.height();
} else {
menuLoc.x += objSize.width();
}
xObjList.addToTail(pObj);
nMenuCount++;
} else {
nRunItems++;
pObj->runObject();
// This detach may cause problems in the future, if it does delete it
// Some object may not work if detached for example midi sound
pObj->detach();
}
}
}
// Start non-wield menu on next row
menuLoc.y += objSize.height();
nNumWieldChoices = xObjList.getCount();
if (nNumWieldChoices != 0) {
cWieldMenuSize = menuSize;
}
}
bool bNoMenu = false;
for (int i = 0; i < getObjectList()->getCount(); ++i) {
pObj = getObjectList()->getNodeItem(i);
if (pObj->isLocal() && (!pObj->getExpression() || pObj->getExpression()->evaluate(pObj->isNegative()))) {
// Only attach if not attached
if (pObj->isAttached() == false) {
pObj->attach();
// Otherwise, we need to re-calculate the size of the text object,
// since we are gonna trash is with our own values soon.
} else if (pObj->getType() == TEXT_OBJ) {
((CBagTextObject *)pObj)->recalcTextRect(((CBagTextObject *)pObj)->isCaption());
}
if (!pObj->isImmediateRun()) {
// Get the next menu items pos
objSize = pObj->getRect();
// If it is a text object increment next position by its height
if (pObj->getType() == TEXT_OBJ) {
if (tmpVal)
// If we have a value move text to next line
menuLoc.y += tmpVal;
tmpVal = 0; // Text objects set the next line to be at the very beginning
// If we're zoomed, then do things differently
CBagTextObject *pTXObj = (CBagTextObject *)pObj;
if (pTXObj->isCaption()) {
SBZoomPda *pZPDA = (SBZoomPda *)g_SDevManager->getStorageDevice("BPDAZ_WLD");
if (pZPDA && pZPDA->getZoomed()) {
bZoomed = true;
wndRect = pZPDA->getViewRect();
}
}
if (bTextOnly) {
if (wndRect.height() <= (objSize.height() + menuLoc.y)) {
menuLoc.y = 1;
nBaseMenuLocX += (menuSize.cx + 2);
menuLoc.x = nBaseMenuLocX + 1;
}
} else if (wndRect.height() <= ((objSize.height() + menuLoc.y) + 41)) {
menuLoc.y = 1;
nBaseMenuLocX += (menuSize.cx + 2);
menuLoc.x = nBaseMenuLocX;
}
// CHECKME: the previous assignment seems to indicate that the following line should be removed in order to keep this slightly different value
menuLoc.x = (1 + nBaseMenuLocX);
if (menuSize.cx < (objSize.width() + menuLoc.x))
menuSize.cx = (objSize.width() + menuLoc.x);
if (menuSize.cy < (objSize.height() + menuLoc.y))
menuSize.cy = (objSize.height() + menuLoc.y);
pObj->setPosition(menuLoc);
pObj->setHighlight(false);
menuLoc.x = (1 + nBaseMenuLocX);
menuLoc.y += (objSize.height() + 1);
} else {
// Increment next position by its width
if (wndRect.height() <= (objSize.height() + menuLoc.y)) {
menuLoc.y = 1;
nBaseMenuLocX += (menuSize.cx + 2);
menuLoc.x = nBaseMenuLocX;
}
bTextOnly = false;
// Continue to grow menu size to max required
if (menuSize.cx < (objSize.width() + menuLoc.x))
menuSize.cx = (objSize.width() + menuLoc.x);
if (menuSize.cy < (objSize.height() + menuLoc.y))
menuSize.cy = (objSize.height() + menuLoc.y);
pObj->setPosition(menuLoc);
pObj->setHighlight(false);
if ((nObjectPal < 0) && ((pObj->getType() == BMP_OBJ) || (pObj->getType() == SPRITE_OBJ)))
nObjectPal = i;
menuLoc.x += objSize.width();
tmpVal = objSize.height();//save the obj height for use later if we get a text obj
}
if (pObj->isNoMenu()) {
bNoMenu = true;
}
xObjList.addToTail(pObj);
nNumItems++;
nMenuCount++;
} else {
nRunItems++;
pObj->runObject();
if (pObj->getType() == LINK_OBJ) {
g_bAAOk = false;
}
}
} // If in local area and activated by expression
}
// If we ran something and there are no other menu items just return
if (!(nRunItems && !nMenuCount)) {
if (nMenuCount) {
menuLoc.y += objSize.height();
menuLoc.x = 1;
nMenuCount = 0;
}
menuSize.cx++;
menuSize.cy++;
CBofRect tmpRect(CBofPoint(x, y - menuSize.cy / 2), menuSize);
menuSize.cy += 2;
// If the menu contains only one object and it is a caption style text object
// position the dialog box at the bottom of the Game window screen
bool bMoved = false;
bool bCaption = false;
int nNumChars = 0;
if ((nNumItems == 1) && (xObjList.getTail()->getNodeItem()->getType() == TEXT_OBJ) && (((CBagTextObject *)xObjList.getTail()->getNodeItem())->isCaption())) {
while (nNumWieldChoices-- != 0) {
pObj = xObjList.removeHead();
pObj->detach();
}
// If we are not using the wield menu with this menu, then
// the menu is smaller
menuSize.cy -= cWieldMenuSize.cy;
if (cWieldMenuSize.cy != 0)
cWieldMenuSize.cy--;
bMoved = true;
tmpRect = wndRect;
tmpRect.top = tmpRect.bottom - menuSize.cy;
bCaption = true;
nNumChars = ((CBagTextObject *)xObjList.getHead()->getNodeItem())->getText().getLength();
// Bring caption back 3 pixels
CBofPoint cPoint;
cPoint = xObjList.getHead()->getNodeItem()->getPosition();
cPoint.x = 1;
xObjList.getHead()->getNodeItem()->setPosition(cPoint);
} else {
if (bTextOnly) {
while (nNumWieldChoices-- != 0) {
pObj = xObjList.removeHead();
pObj->detach();
}
// If we are not using the wield menu with this menu, then
// the menu is smaller
menuSize.cy -= cWieldMenuSize.cy;
bMoved = true;
}
// Use the mouse pos (x,y), and add the menuSize calculated above
tmpRect.left = x;
tmpRect.top = y;
tmpRect.bottom = y + menuSize.cy;
tmpRect.right = x + menuSize.cx + 1;
// If the menu would go off the screen, adjust it
while (tmpRect.top < wndRect.top) {
tmpRect.offsetRect(0, (wndRect.top - tmpRect.top));
}
while (tmpRect.bottom > wndRect.bottom) {
tmpRect.offsetRect(0, (wndRect.bottom - tmpRect.bottom));
}
while (tmpRect.left < wndRect.left) {
tmpRect.right += (wndRect.left - tmpRect.left);
tmpRect.left += (wndRect.left - tmpRect.left);
}
while (tmpRect.right > wndRect.right) {
tmpRect.left -= (tmpRect.right - wndRect.right);
tmpRect.right -= (tmpRect.right - wndRect.right);
}
}
bReturn = false;
if (xObjList.getCount() && !bNoMenu) {
bReturn = true;
dlg.setObjectList(&xObjList);
for (int i = 0; i < xObjList.getCount(); i++) {
pObj = xObjList[i];
if (pObj->getType() == TEXT_OBJ) {
int cx = tmpRect.size().cx - 1;
int cy = tmpRect.size().cy - 1;
if (!bCaption) {
cy = ((CBagTextObject *)pObj)->getSize().cy + 2;
}
pObj->setSize(CBofSize(cx, cy));
// Need to move the menus up when have a wielded item, but
// not displaying the wield menu
if (bMoved) {
CBofPoint cPos;
cPos = pObj->getPosition();
cPos.y -= cWieldMenuSize.cy;
pObj->setPosition(cPos);
}
}
}
CBagPanWindow::flushInputEvents();
// If we were requested to put a dialog over the PDA, then shift it upward
// a bit... unless of course the mousedown occurred in the PDA itself.
CBagPDA *pPDA = (CBagPDA *)g_SDevManager->getStorageDevice("BPDA_WLD");
if (pPDA != nullptr && (pPDA->isActivated() && bZoomed == false)) {
if (!pPDA->isInside(cMouseDown)) {
CBofRect cPDARect = pPDA->getRect();
tmpRect.offsetRect(0, (tmpRect.bottom > cPDARect.top ? cPDARect.top - tmpRect.bottom : 0));
// Make sure we didn't go too far
if (tmpRect.top < 0) {
tmpRect.offsetRect(0, -tmpRect.top);
}
}
}
// Force all menus to be created using a specific palette
// that we know contains the correct colors for our menu.
char szBuf[256];
Common::strcpy_s(szBuf, EXAMINEBMP);
CBofString cString(szBuf, 256);
fixPathName(cString);
CBofPalette xPal;
xPal.loadPalette(cString);
dlg.createDlg(pParent, &xPal, &tmpRect);
if (bCaption) {
// We need to move this back to the correct position
// because the Boflibs center dialog ALWAYS !!!!!!!!
// If the PDA is currently active, then we have to put the caption elsewhere,
// or deactivate the PDA (if PDA zoomed, just place at bottom.
if (CBagPanWindow::_pPDABmp != nullptr && CBagPanWindow::_pPDABmp->isActivated() && bZoomed == false) {
dlg.move(wndRect.left, wndRect.top, true);
} else {
dlg.move(tmpRect.left, tmpRect.top, true);
}
// Need to re-save the background because there is a bug with moving
// the dialog box.
dlg.saveBackground();
// Set this caption to automatically go away after specified delay
if (_nDelay > 0) {
dlg.setTimer(TIMER_CLOSE_ID, _nDelay + (80 * nNumChars));
}
} else {
dlg.move(tmpRect.topLeft().x, tmpRect.topLeft().y, true);
// Need to re-save the background because there is a bug with moving
// the dialog box.
dlg.saveBackground();
}
CBagPanWindow::flushInputEvents();
g_pauseTimerFl = true;
dlg.doModal();
g_pauseTimerFl = false;
pObj = dlg._pSelectedObject;
dlg.destroy();
for (int i = 0; i < getObjectCount(); ++i) {
getObjectByPos(i)->detach();
}
// If our current storage device is "AS CUSTOM" then don't allow
// the timer to get incremented.
CBagStorageDev *pCurSDEV = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
if (pObj != nullptr) {
pObj->runCallBack();
// Selecting this menu item causes a turn to go by
if (nNumCalls == 1 && pCurSDEV->isCustom() == false) {
g_VarManager->incrementTimers();
}
} else if (bCaption && (nNumCalls == 2)) {
// Selecting this menu item causes a turn to go by
dlg._pSelectedObject = nullptr;
if (pCurSDEV->isCustom() == false) {
g_VarManager->incrementTimers();
}
}
}
}
nNumCalls--;
return bReturn;
}
bool CBagMenu::addItem(CBagObject *pObj, void *(* /*func*/)(int, void *), void */*info*/) {
pObj->setPosition(CBofPoint(0, _nY));
_nY = (int16)(_nY + (int16)(pObj->getRect().height() + 1));
addObject(pObj);
return true;
}
bool CBagMenu::deleteItem(const CBofString & /*sLabel*/) {
return false;
}
bool CBagMenu::isChecked(const CBofString & /*sLabel*/, const CBofString & /*sSubLabel*/) {
const int nRow = 0;
const int nCol = 0;
return isCheckedPos(nRow, nCol);
}
bool CBagMenu::isCheckedPos(int /*nRow*/, int /*nCol*/) {
return false;
}
bool CBagMenu::isChecked(int /*nRefId*/) {
return false;
}
bool CBagMenu::check(const CBofString & /*sLabel*/, const CBofString & /*sSubLabel*/) {
return false;
}
bool CBagMenu::unCheck(const CBofString & /*sLabel*/, const CBofString & /*sSubLabel*/) {
return false;
}
bool CBagMenu::check(int /*nRefId*/) {
return true;
}
bool CBagMenu::unCheck(int /*nRefId*/) {
return true;
}
bool CBagMenu::setUniversalObjectList(CBofList<CBagObject *> *pObjList) {
if (_pUniversalObjectList != nullptr) {
removeUniversalObjectList();
}
_pUniversalObjectList = pObjList;
return true;
}
bool CBagMenu::removeUniversalObjectList() {
if (_pUniversalObjectList == nullptr) {
return true;
}
_pUniversalObjectList = nullptr;
return true;
}
//
//
//
CBagMenuDlg::CBagMenuDlg() {
// Remove this SDEV from the storage device list so that it is not deleted
// when we switch .WLD files, and there may still be a Dialog open.
g_SDevManager->unregisterStorageDev(this);
_bAcceptInput = false;
_bMultipleDialogs = false;
}
CBagMenuDlg::~CBagMenuDlg() {
assert(isValidObject(this));
}
ErrorCode CBagMenuDlg::createDlg(CBofWindow *pWnd, CBofPalette *pPal, CBofRect *pRect) {
CBofRect r;
_bMultipleDialogs = false;
_bAcceptInput = true;
_nReturnValue = 0;
if (!pRect) {
r = pWnd->getWindowRect();
r.offsetRect(-r.left, -r.top);
r.bottom = r.top + MENU_DFLT_HEIGHT;
} else {
r = *pRect;
}
CBagStorageDevDlg::create("Menu", &r, pWnd, 0);
CBofBitmap *pBmp = new CBofBitmap(r.width(), r.height(), pPal);
r.offsetRect(-r.left, -r.top);
assert(pPal != nullptr);
pBmp->fillRect(&r, pPal->getNearestIndex(RGB(82, 82, 82)));
pBmp->drawRect(&r, pPal->getNearestIndex(RGB(0, 0, 0)));
setBackdrop(pBmp);
return _errCode;
}
void CBagMenuDlg::onLButtonUp(uint32 nFlags, CBofPoint *pPoint, void *) {
// We are ignoring all input until the dialog is actually visible
if (_bAcceptInput) {
_pSelectedObject = nullptr;
onClose();
if (_bMultipleDialogs) {
CBofRect r = getWindowRect();
r.offsetRect(-r.left, -r.top);
if (r.ptInRect(*pPoint)) {
CBagStorageDevDlg::onLButtonUp(nFlags, pPoint);
_pSelectedObject = getLActiveObject();
}
} else {
const CBofPoint pt = devPtToViewPort(*pPoint);
_pSelectedObject = getObject(pt);
if (_pSelectedObject != nullptr) {
_pSelectedObject->onLButtonUp(nFlags, pPoint);
}
}
_nReturnValue = (_pSelectedObject != nullptr);
}
}
void CBagMenuDlg::onMouseMove(uint32 /*nFlags*/, CBofPoint *pPoint, void *) {
CBagMasterWin::setActiveCursor(0);
CBagObject *pObj = getObject(*pPoint);
if (pObj != nullptr) {
// Switch to that cursor
CBagMasterWin::setActiveCursor(pObj->getOverCursor());
if (pObj != getLActiveObject()) {
if (pObj->getCallBack() || pObj->getMenuPtr()) {
pObj->setHighlight();
if (getLActiveObject())
getLActiveObject()->setHighlight(false);
setLActiveObject(pObj);
}
}
}
}
void CBagMenuDlg::onTimer(uint32 nID) {
assert(isValidObject(this));
switch (nID) {
// Auto close for text-Captions
case TIMER_CLOSE_ID:
killTimer(nID);
close();
break;
// Can now allow user input
case TIMER_HACK_ID:
killTimer(nID);
_bAcceptInput = true;
break;
default:
logWarning("Invalid Timer ID");
break;
}
}
void CBagMenuDlg::onPaint(CBofRect *pRect) {
assert(isValidObject(this));
CBagStorageDevDlg::onPaint(pRect);
// Don't allow user input until this menu is visible
CBagPanWindow::flushInputEvents();
}
void CBagMenuDlg::onDeActivate() {
assert(isValidObject(this));
close();
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,105 @@
/* 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 BAGEL_BAGLIB_MENU_DLG_H
#define BAGEL_BAGLIB_MENU_DLG_H
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/baglib/sprite_object.h"
namespace Bagel {
namespace SpaceBar {
class CBagMenu : public CBagStorageDev {
private:
static CBofList<CBagObject *> *_pUniversalObjectList; // Objects used in every menu
static int _nDefaultDelay;
int16 _nDelay;
int16 _nY; // Replaces _nNextPos
public:
CBagMenu();
static void initialize();
ErrorCode setBackground(CBofBitmap * /*pBmp*/) {
assert(false);
return ERR_NONE;
}
CBofBitmap *getBackground() {
assert(false);
return nullptr;
}
bool addItem(CBagObject *pObj, void *(*func)(int, void *), void *info);
bool deleteItem(const CBofString &sLabel);
bool isChecked(const CBofString &sLabel, const CBofString &sSubLabel = CBofString());
bool isChecked(int nRefId);
bool isCheckedPos(int nRow, int nCol = -1);
bool check(const CBofString &sLabel, const CBofString &sSubLabel = CBofString());
bool check(int nRefId);
bool unCheck(const CBofString &sLabel, const CBofString &sSubLabel = CBofString());
bool unCheck(int nRefId);
bool trackPopupMenu(uint32 nFlags, int x, int y, CBofWindow *pWnd, CBofPalette *pPal, CBofRect *lpRect = nullptr);
static bool removeUniversalObjectList();
static bool setUniversalObjectList(CBofList<CBagObject *> *pObjList);
static CBofList<CBagObject *> *getUniversalObjectList() {
return _pUniversalObjectList;
}
CBagObject *onNewSpriteObject(const CBofString &);
};
class CBagMenuDlg : public CBagStorageDevDlg {
friend class CBagMenu;
private:
bool _bMultipleDialogs;
bool _bAcceptInput;
public:
static CBagObject *_pSelectedObject;
static void initialize();
CBagMenuDlg();
virtual ~CBagMenuDlg();
ErrorCode createDlg(CBofWindow *pWnd, CBofPalette *pPal, CBofRect *cRect);
virtual void onMouseMove(uint32 nFlags, CBofPoint *pPoint, void * = nullptr);
virtual void onLButtonUp(uint32 nFlags, CBofPoint *pPoint, void * = nullptr);
virtual void onDeActivate();
virtual void onTimer(uint32 nID);
virtual void onPaint(CBofRect *pRect);
};
extern bool g_pauseTimerFl;
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,122 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/moo.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
namespace Bagel {
namespace SpaceBar {
CBagCharacterObject *CBagMoo::_pMovie;
PdaMode CBagMoo::_eSavePDAMode;
PdaPos CBagMoo::_eSavePDAPos;
void CBagMoo::initialize() {
_pMovie = nullptr;
_eSavePDAMode = PDA_NO_MODE;
_eSavePDAPos = PDA_POS_UNINITIALIZED;
}
ErrorCode CBagMoo::update(CBofBitmap *pBmp, CBofPoint /*pt*/, CBofRect *pSrcRect, int nMaskColor) {
ErrorCode errorCode = ERR_NONE;
if (_pMovie) {
// Update the movie, assume only unzoomed pda right now
const CBofPoint cPos(116, 61);
errorCode = _pMovie->update(pBmp, cPos, pSrcRect, nMaskColor);
// If we're done or we encountered an error, then roll over and die.
if (errorCode != ERR_NONE || _pMovie->isModalDone()) {
stopMovie(true);
}
}
return errorCode;
}
CBagMoo::~CBagMoo() {
// Can possibly have a movie left over.
delete _pMovie;
_pMovie = nullptr;
}
ErrorCode CBagMoo::setPDAMovie(CBofString &s) {
// Should never happen, but just make sure.
delete _pMovie;
_pMovie = nullptr;
// Get a new movie object
_pMovie = new CBagCharacterObject();
_pMovie->setFileName(s);
// Attach this bad baby...
const ErrorCode errorCode = _pMovie->attach();
if (errorCode == ERR_NONE) {
_pMovie->setModal(false);
_pMovie->setNumOfLoops(1);
}
return errorCode;
}
void CBagMoo::stopMovie(bool bResetPDA) {
CBagPDA *pPDA = (CBagPDA *)g_SDevManager->getStorageDevice("BPDA_WLD");
if (bResetPDA) {
if (pPDA) {
// Assume this marks the end of the movie.
switch (_eSavePDAMode) {
case PDA_MAP_MODE:
pPDA->showMap();
break;
case PDA_INV_MODE:
pPDA->showInventory();
break;
case PDA_LOG_MODE:
pPDA->showLog();
break;
case PDA_NO_MODE:
default:
pPDA->hideMovie();
break;
}
}
}
if (_pMovie) {
_pMovie->detach();
delete _pMovie;
_pMovie = nullptr;
}
// If we're done playing, then deactivate the PDA.
if (pPDA && pPDA->getDeactivate() == true && pPDA->isActivated()) {
pPDA->deactivate();
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,76 @@
/* 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 BAGEL_BAGLIB_MOO_H
#define BAGEL_BAGLIB_MOO_H
#include "bagel/spacebar/baglib/storage_dev_bmp.h"
#include "bagel/spacebar/baglib/character_object.h"
#include "bagel/spacebar/baglib/pda.h"
namespace Bagel {
namespace SpaceBar {
class CBagMoo : public CBagStorageDevBmp {
private:
static CBagCharacterObject *_pMovie;
static PdaMode _eSavePDAMode;
static PdaPos _eSavePDAPos;
public:
CBagMoo() : CBagStorageDevBmp() {
}
virtual ~CBagMoo();
static void initialize();
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect = nullptr, int nMaskColor = -1) override;
// Grab the button event of the bagbmobj and send them to the cbagsdev
void onLButtonUp(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void */*info*/) override {
}
void onLButtonDown(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr) override {
}
// For public access to our movie object
ErrorCode setPDAMovie(CBofString &s);
CBagCharacterObject *getPDAMovie() {
return _pMovie;
}
void stopMovie(bool);
bool moviePlaying() {
return _pMovie != nullptr;
}
void savePDAMode(PdaMode pdaMode) {
_eSavePDAMode = pdaMode;
}
void savePDAPosition(PdaPos pdaPos) {
_eSavePDAPos = pdaPos;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,538 @@
/* 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/>.
*
*/
#include "common/file.h"
#include "bagel/spacebar/baglib/movie_object.h"
#include "bagel/spacebar/baglib/exam.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/boflib/sound.h"
#include "bagel/spacebar/baglib/fmovie.h"
#include "bagel/spacebar/baglib/zoom_pda.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/log.h"
namespace Bagel {
namespace SpaceBar {
#define SOUND_FILE_EXT_LOWER ".wav"
#define SOUND_FILE_EXT_UPPER ".WAV"
#define OVERRIDE_SMK "$SBARDIR\\BAR\\LOG\\OVERRIDE.SMK"
CBagMovieObject::CBagMovieObject() {
_xObjType = MOVIE_OBJ;
setVisible(true);
_xDisplayType = dispType::MOVIE;
_bFlyThru = false;
// Initialize asynch flags to be off by default.
_nAsynchFlags = 0;
// Allow user to force movie not to increment (default = increment = true)
setIncrement();
// Allow movie to play on a black background (default, nada).
setOnBlack(false);
// Default is no associated sound.
setAssociatedSound(nullptr);
}
CBagMovieObject::~CBagMovieObject() {
CBagObject::detach();
// Could still by lying around in the pda movie queue,
// Make sure it has been removed.
if (_xDisplayType == dispType::ASYNCH_PDA_MSG) {
CBagPDA::removeFromMovieQueue(this);
}
// If there's a sound with this guy, then trash it here.
if (getAssociatedSound()) {
delete getAssociatedSound();
setAssociatedSound(nullptr);
}
}
bool CBagMovieObject::runObject() {
CBofWindow *pNewWin = nullptr;
SBZoomPda *pPDAz = (SBZoomPda *)g_SDevManager->getStorageDevice("BPDAZ_WLD");
const bool bZoomed = (pPDAz == nullptr ? false : pPDAz->getZoomed());
// Get a pointer to the current game window
CBagStorageDevWnd *pMainWin = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev();
bool rc = true;
if (!_bFlyThru || CBagMasterWin::getFlyThru()) {
rc = false;
CBofString sFileName = getFileName();
const int nExt = sFileName.getLength() - 4; // ".EXT"
if (nExt <= 0) {
logError("Movie does not have a file name or proper extension. Please write better scripts.");
return rc;
}
//
// This would be much cooler if it were a cast to another object type and
// then a run. But this is a quicker fix.
//
enum class MovieFileType {
NONE = 0,
TEXT = 1,
SOUND = 2,
MOVIE = 3
} nMovFileType;
const CBofString sBaseStr = sFileName.left(nExt);
if (sFileName.find(".smk") > 0 || sFileName.find(".SMK") > 0) {
nMovFileType = MovieFileType::MOVIE;
} else if (sFileName.find(SOUND_FILE_EXT_LOWER) > 0 || sFileName.find(SOUND_FILE_EXT_UPPER) > 0) {
nMovFileType = MovieFileType::SOUND;
} else if (sFileName.find(".txt") > 0 || sFileName.find(".TXT") > 0) {
nMovFileType = MovieFileType::TEXT;
} else {
nMovFileType = MovieFileType::NONE;
}
// Look for .SMK then .WAV, then .TXT
while (!fileExists(sFileName.getBuffer())) {
switch (nMovFileType) {
case MovieFileType::MOVIE:
sFileName = sBaseStr + SOUND_FILE_EXT_LOWER;
nMovFileType = MovieFileType::SOUND;
break;
case MovieFileType::SOUND:
sFileName = sBaseStr + ".txt";
nMovFileType = MovieFileType::TEXT;
break;
case MovieFileType::TEXT:
bofMessageBox(sFileName.getBuffer(), "Could not find asset");
nMovFileType = MovieFileType::NONE;
break;
// We should never get here
case MovieFileType::NONE:
default:
logError(buildString("Movie does not have a correct file name: %s.", sFileName.getBuffer()));
return rc;
}
}
if (nMovFileType == MovieFileType::MOVIE) {
bool isFiltered = false;
CBagMasterWin *pWnd = CBagel::getBagApp()->getMasterWnd();
CBagStorageDevWnd *pSDevWnd = (pWnd ? pWnd->getCurrentStorageDev() : nullptr);
// Get the pda here, we need it so much anyway.
CBagPDA *pPDA = (CBagPDA *)g_SDevManager->getStorageDevice("BPDA_WLD");
assert(pPDA != nullptr);
// If we have an asnych movie to play, make sure it is a good
// time to play it, if not, then queue it up so it can play at a much better time.
if (_xDisplayType == dispType::ASYNCH_PDA_MSG) {
if (asynchPDAMovieCanPlay() == false) {
pPDA->addToMovieQueue(this);
return rc;
}
} else if ((pWnd != nullptr) && (pSDevWnd != nullptr)) {
// Don't need to redraw for asynch pda messages, this just
// messes things up in the PDA redraw code
pSDevWnd->paintScreen(nullptr);
isFiltered = pSDevWnd->isFiltered();
}
if (_xDisplayType == dispType::EXAMINE) {
CBofRect r(160, 60, 480, 300);
// Offset the rect for the movies to compensate for all screen sizes
r.offsetRect(((CBofWindow *)pMainWin)->getWindowRect().topLeft());
// If we have a movie playing in the zoom pda, then black out
// the background. Examine movies will always play with a black background
// on the mac (prevents a palette shift).
CBagExam *pMovie = new CBagExam(CBagel::getBagApp()->getMasterWnd()->getCurrentGameWindow(), sFileName, &r);
// If there is an associated sound file, then start it up here.
CBagSoundObject *pSObj = getAssociatedSound();
if (pSObj) {
if (pSObj->isAttached() == false) {
pSObj->attach();
}
pSObj->runObject();
}
CBofWindow *wnd = CBagel::getBagApp()->getMasterWnd();
pMovie->show();
CBofApp::getApp()->getMainWindow()->flushAllMessages();
wnd->flushAllMessages();
pMovie->initExam();
delete pMovie;
// As soon as we're done, detach (this will also stop the sound).
if (pSObj) {
pSObj->detach();
}
} else {
bool bActivated = false;
CBofRect r(80, 10, 80 + 480 - 1, 10 + 360 - 1);
// Offset the rect for the movies to compensate for all screen sizes
r.offsetRect(((CBofWindow *)pMainWin)->getWindowRect().topLeft());
if (_xDisplayType == dispType::PDA_MSG || _xDisplayType == dispType::ASYNCH_PDA_MSG) {
// Pull up the PDA (if it exists)
// Only pull up the PDA if we're not playing an asynch movie
if (_xDisplayType == dispType::PDA_MSG) {
// Increment timer one, pda message counts as one turn
// Allow scripter to override timer increment
if (isIncrement()) {
g_VarManager->incrementTimers();
}
}
if (pMainWin->getDeviceType() == SDEV_GAMEWIN) {
// If the pda is going up or down, then wait for it
// To do its thing before attempting to activate it.
if (pPDA->isActivating()) {
((CBagPanWindow *)pMainWin)->waitForPDA();
}
if (pPDA->isActivated() == false) {
bActivated = ((CBagPanWindow *)pMainWin)->activatePDA();
((CBagPanWindow *)pMainWin)->waitForPDA();
}
}
} else {
// Pull down the PDA (if it exists)
if (pMainWin->getDeviceType() == SDEV_GAMEWIN) {
((CBagPanWindow *)pMainWin)->deactivatePDA();
((CBagPanWindow *)pMainWin)->waitForPDA();
}
}
// Use the position scripted for the movie if it exists
// The bottom, right is unimportant because movie won't resize anyway
CBofPoint p = CBagObject::getPosition();
if (p.x != -1 && p.y != -1)
r.offsetRect(p);
if (isFiltered) {
if (bZoomed) {
pNewWin = new CBofWindow();
pNewWin->create("BLACK", 0, 0, 640, 480, CBofApp::getApp()->getMainWindow(), 0);
pNewWin->fillWindow(COLOR_BLACK);
}
CBagFMovie *pMovie = new CBagFMovie(CBofApp::getApp()->getMainWindow(), sFileName, &r);
if (pMovie->errorOccurred())
logError(buildString("Movie file could not be read: %s. How? You removed that CD again didn't you", sFileName.getBuffer()));
else {
pMovie->show();
CBofApp::getApp()->getMainWindow()->flushAllMessages();
pWnd->flushAllMessages();
pMovie->play(false);
}
delete pMovie;
pMovie = nullptr;
delete pNewWin;
pNewWin = nullptr;
} else {
// Hack.. allow script to override some other movies.
if ((_xDisplayType == dispType::PDA_MSG) && pMainWin->isCIC() && isDontOverride() == false) {
char szLocalBuff[256];
CBofString cStr(szLocalBuff, 256);
// Play the override message.
cStr = OVERRIDE_SMK;
fixPathName(cStr);
sFileName = cStr;
}
if (_xDisplayType == dispType::ASYNCH_PDA_MSG) {
// Tell our PDA to switch gears to do asynch movie time.
if (pPDA->showMovie()) { // Returns false if another movie playing
pPDA->setMovie(sFileName); // Set the movie to play
}
} else {
CBofMovie *pMovie;
if (bZoomed && _xDisplayType != dispType::PDA_MSG) {
pNewWin = new CBofWindow();
pNewWin->create("BLACK", 0, 0, 640, 480, CBofApp::getApp()->getMainWindow(), 0);
pNewWin->show();
pNewWin->fillWindow(COLOR_BLACK);
}
// If playing a PDA message while the PDA is zoomed
if (bZoomed && _xDisplayType == dispType::PDA_MSG) {
// Then stretch it to fit into the PDA's viewscreen
r.setRect(24, 47, 28 + 600 - 1, 47 + 302 - 1);
pMovie = new CBofMovie(CBofApp::getApp()->getMainWindow(), sFileName, &r, true);
} else {
// Otherwise, just play the movie normally
pMovie = new CBofMovie(CBofApp::getApp()->getMainWindow(), sFileName, &r);
}
if (pMovie->errorOccurred())
logError(buildString("Movie file could not be read: %s. How? You removed that CD again didn't you", sFileName.getBuffer()));
else {
// Stop any asnych movies already playing
pPDA->stopMovie(true);
pMovie->show();
CBofApp::getApp()->getMainWindow()->flushAllMessages();
pWnd->flushAllMessages();
pMovie->play(false);
}
delete pMovie;
pMovie = nullptr;
// If we put a black window up, then
delete pNewWin;
pNewWin = nullptr;
}
}
// Put the pda down if we brought it up. (8638)
if (_xDisplayType != dispType::ASYNCH_PDA_MSG && bActivated) {
((CBagPanWindow *)pMainWin)->deactivatePDA();
((CBagPanWindow *)pMainWin)->waitForPDA();
}
// If we're asynch, then let it know to deactivate when done playing.
if (_xDisplayType == dispType::ASYNCH_PDA_MSG) {
pPDA->setDeactivate(bActivated);
}
}
// Movies usually mark the transition from one view to another
// but not necessarily a change of sdev's, so make sure we repaint the
// backdrop
pMainWin->setPreFilterPan(true);
} else if (nMovFileType == MovieFileType::SOUND) {
CBofSound *pSound = new CBofSound(CBofApp::getApp()->getMainWindow(), sFileName, SOUND_WAVE);
pSound->play();
delete pSound;
} else if (nMovFileType == MovieFileType::TEXT) {
Common::File f;
if (f.open(sFileName.getBuffer())) {
Common::String line = f.readLine();
bofMessageBox(line.c_str(), "Incoming Message...");
f.close();
} else {
logError(buildString("Movie TEXT file could not be read: %s. Why? because we like you ...", sFileName.getBuffer()));
}
}
rc = CBagObject::runObject();
}
return rc;
}
ParseCodes CBagMovieObject::setInfo(CBagIfstream &istr) {
bool nObjectUpdated = false;
char szLocalStr[256];
CBofString sStr(szLocalStr, 256);
while (!istr.eof()) {
istr.eatWhite(); // Eat any white space between script elements
const char ch = (char)istr.peek();
switch (ch) {
//
// AS - n number of slides in sprite
//
case 'A': {
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("AS")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("EXAMINE")) {
_xDisplayType = dispType::EXAMINE;
} else if (!sStr.find("MOVIE")) {
_xDisplayType = dispType::MOVIE;
} else if (!sStr.find("FLYTHRU")) {
_xDisplayType = dispType::MOVIE;
_bFlyThru = true;
} else if (!sStr.find("PDAMSG")) {
_xDisplayType = dispType::PDA_MSG;
} else if (!sStr.find("ASYNCH_PDAMSG")) {
_xDisplayType = dispType::ASYNCH_PDA_MSG;
// see if this improves performance any...
setPreload(true);
}
}
nObjectUpdated = true;
}
break;
// Don't queue attribute, when set, the asynch movie either plays
// immediately or not at all.
case 'D': {
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("DONTQUEUE")) {
setDontQueue();
nObjectUpdated = true;
} else if (!sStr.find("DONTOVERRIDE")) {
setDontOverride();
nObjectUpdated = true;
} else if (!sStr.find("DONTINCREMENT")) {
// Don't increment the timer when playing this movie
setIncrement(false);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
// Don't queue attribute, when set, the asynch movie either plays
// immediately or not at all.
case 'P': {
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("PLAYIMMEDIATE")) {
setPlayImmediate();
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
// This is probably going to be much more important to the
// mac version... give the option of playing the movie on a black
// background. this solves the problem of palette shifts on examine
// movies.
case 'O': {
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("ONBLACK")) {
setPlayImmediate();
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
// Associate a sound file with this movie (primarily for examine
// movies).
case 'S': {
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("SND")) {
nObjectUpdated = true;
_pSndObj = new CBagSoundObject();
if (_pSndObj->setInfo(istr) == PARSING_DONE) {
return PARSING_DONE;
}
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
//
// No match return from function
//
default: {
const ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
nObjectUpdated = true;
} else { // rc==UNKNOWN_TOKEN
if (nObjectUpdated)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
}
break;
}
}
return PARSING_DONE;
}
bool CBagMovieObject::asynchPDAMovieCanPlay() {
// Don't play movie if we're zoomed or if we're in a CIC
// or a sound is playing or another movie is playing...
bool bCanPlay = true;
// Obvious case, if it is set for immediate, return true.
if (isPlayImmediate()) {
return bCanPlay;
}
char szLocalBuff[256];
CBofString sStr(szLocalBuff, 256);
sStr = "BPDAZ_WLD";
SBZoomPda *pPDAz = (SBZoomPda *)g_SDevManager->getStorageDevice(sStr);
sStr = "BPDA_WLD";
CBagPDA *pPDA = (CBagPDA *)g_SDevManager->getStorageDevice(sStr);
CBagPanWindow *pMainWin = (CBagPanWindow *)(CBagel::getBagApp()->getMasterWnd()->getCurrentGameWindow());
// Queue this message if any one of a variety of things is happening.
assert(pPDA != nullptr);
assert(pPDAz != nullptr);
if (pPDA && pPDAz) {
if (pPDAz->getZoomed() || // We're zoomed
(pMainWin->isCIC() && !isDontOverride()) || // We're in a character closeup
CBofSound::soundsPlayingNotOver() || // A sound is playing
pPDA->getPdaMode() == PDA_MOO_MODE) { // An asynch movie is already playing
bCanPlay = false;
}
}
return bCanPlay;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,118 @@
/* 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 BAGEL_BAGLIB_MOVIE_OBJECT_H
#define BAGEL_BAGLIB_MOVIE_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/baglib/sound_object.h"
namespace Bagel {
namespace SpaceBar {
#define ASYNCH_DONT_QUEUE 0x0001
#define ASYNCH_PLAY_IMMEDIATE 0x0002
#define ASYNCH_DONT_OVERRIDE 0x0004
/**
* CBagMovieObject is an object that can be place within the slide window.
*/
class CBagMovieObject : public CBagObject {
public:
enum class dispType {
MOVIE, EXAMINE, PDA_MSG, ASYNCH_PDA_MSG
};
private:
dispType _xDisplayType;
byte _bFlyThru;
int16 _nAsynchFlags;
bool _bIncrement : 1; // Increment timer for this movie?
bool _bOnBlack : 1; // Play movie on a black background.
CBagSoundObject *_pSndObj; // associated sound object
public:
CBagMovieObject();
virtual ~CBagMovieObject();
// Associated sound object access members
void setAssociatedSound(CBagSoundObject *p) {
_pSndObj = p;
}
CBagSoundObject *getAssociatedSound() const {
return _pSndObj;
}
ParseCodes setInfo(CBagIfstream &istr) override;
bool runObject() override;
// Return true if this asynch zelda movie can play right now
bool asynchPDAMovieCanPlay();
// Special routines for handling asynch zelda movies
void setDontQueue() {
_nAsynchFlags |= ASYNCH_DONT_QUEUE;
}
void setDontOverride() {
_nAsynchFlags |= ASYNCH_DONT_OVERRIDE;
}
void setPlayImmediate() {
_nAsynchFlags |= ASYNCH_PLAY_IMMEDIATE;
}
void setIncrement(bool b = true) {
_bIncrement = b;
}
void setOnBlack(bool b = true) {
_bOnBlack = b;
}
bool isDontQueue() const {
return (_nAsynchFlags & ASYNCH_DONT_QUEUE) != 0;
}
bool isDontOverride() const {
return (_nAsynchFlags & ASYNCH_DONT_OVERRIDE) != 0;
}
bool isPlayImmediate() const {
return (_nAsynchFlags & ASYNCH_PLAY_IMMEDIATE) != 0;
}
bool isIncrement() const {
return _bIncrement;
}
bool isOnBlack() const {
return _bOnBlack;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,469 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/baglib/menu_dlg.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/boflib/file_functions.h"
namespace Bagel {
namespace SpaceBar {
extern bool g_noMenuFl;
CBofString getStringTypeOfObject(BagObjectType n) {
switch (n) {
case BASE_OBJ:
return "UKN";
case BMP_OBJ:
return "BMP";
case SPRITE_OBJ:
return "SPR";
case BUTTON_OBJ:
return "BUT";
case SOUND_OBJ:
return "SND";
case LINK_OBJ:
return "LNK";
case RESPRNT_OBJ:
return "RPO";
case DOSSIER_OBJ:
return "DOS";
case CHAR_OBJ:
return "CHR";
case AREA_OBJ:
return "ARE";
case MOVIE_OBJ:
return "MOVIE";
case VAR_OBJ:
return "VAR";
case COMMAND_OBJ:
return "COMMAND";
case THING_OBJ:
return "TNG";
default:
return "UKN";
};
}
CBagObject::CBagObject() {
_xObjType = BASE_OBJ;
_nX = -1;
_nY = -1;
// All objects now default to timeless
_nProperties = TIMELESS;
_nId = 0;
_nOverCursor = 0;
// Init state
_nState = 0;
_pMenu = nullptr;
_pEvalExpr = nullptr;
_bInteractive = true;
_bNoMenu = false;
// Allocate this on an as-needed basis...
_psName = nullptr;
// Object is dirty by default, doesn't break anything else
// Some objects such as the pda message light are always updated
setDirty(true);
setAlwaysUpdate(false);
// All messages start as not message waiting.
setMsgWaiting(false);
}
CBagObject::~CBagObject() {
delete _pMenu;
_pMenu = nullptr;
if (_psName && (_psName != &_sFileName)) {
delete _psName;
}
_psName = nullptr;
}
ErrorCode CBagObject::attach() {
setVisible();
return CBagParseObject::attach();
}
ErrorCode CBagObject::detach() {
setVisible(false);
return CBagParseObject::detach();
}
ErrorCode CBagObject::update(CBofBitmap * /*pBmp*/, CBofPoint /*pt*/, CBofRect * /*pSrcRect*/, int /*nMaskColor*/) {
return ERR_NONE;
}
bool CBagObject::onObjInteraction(CBagObject *, CBagStorageDev *) {
return false;
}
void CBagObject::setTimeless(bool b) {
setProperty(TIMELESS, b);
}
bool CBagObject::isForeGround() {
return isProperty(FOREGROUND);
}
void CBagObject::setForeGround(bool b) {
setProperty(FOREGROUND, b);
}
int CBagObject::getProperties() {
return _nProperties;
}
void CBagObject::setProperties(int nProperties) {
_nProperties = (uint16)nProperties;
}
const CBofString *CBagObject::getInitInfo() const {
return nullptr;
}
int CBagObject::getProperty(const CBofString &sProp) {
if (!sProp.find("STATE"))
return getState();
if (!sProp.find("MODAL"))
return isModal();
return 0;
}
void CBagObject::setProperty(const CBofString &sProp, int nVal) {
if (!sProp.find("STATE"))
setState(nVal);
else if (!sProp.find("TIMELESS")) {
if (nVal)
setTimeless();
else
setTimeless(false);
} else if (!sProp.find("MODAL")) {
if (nVal)
setModal();
else
setModal(false);
}
}
void CBagObject::setProperty(BAG_OBJECT_PROPERTIES xProp, bool bVal) {
if (bVal)
_nProperties |= xProp;
else
_nProperties &= ~xProp;
}
bool CBagObject::runObject() {
if (isTimeless())
return true;
g_VarManager->incrementTimers();
return true;
}
void CBagObject::setRefId(int id) {
assert(id >= 0 && id <= 0xFFFF);
_nId = (uint16)id;
}
void CBagObject::setOverCursor(int curs) {
_nOverCursor = (byte)curs;
}
void CBagObject::setState(int state) {
assert(ABS(state) < 0x8000);
_nState = (int16)state;
}
void CBagObject::setPosition(const CBofPoint &pos) {
_nX = (int16)pos.x;
_nY = (int16)pos.y;
}
ParseCodes CBagObject::setInfo(CBagIfstream &istr) {
ParseCodes parseCode = UNKNOWN_TOKEN;
while (!istr.eof()) {
istr.eatWhite();
const char ch = (char)istr.getCh();
switch (ch) {
//
// =filename.ext
//
case '=': {
parseCode = UPDATED_OBJECT;
char szLocalBuff[256];
szLocalBuff[0] = 0;
CBofString s(szLocalBuff, 256);
getAlphaNumFromStream(istr, s);
fixPathName(s);
setFileName(s);
break;
}
//
// { menu objects .... } - Add menu items
//
case '{': {
parseCode = UPDATED_OBJECT;
if (!_pMenu) {
_pMenu = new CBagMenu;
// Try to cut down the number of Storage Devices by
// removing these unused ones from the list.
//
g_SDevManager->unregisterStorageDev(_pMenu);
}
istr.putBack();
char szBuff[256];
Common::sprintf_s(szBuff, "Menu:%d", CBagMasterWin::_menuCount++);
CBofString s(szBuff, 256);
_pMenu->loadFileFromStream(istr, s, false);
}
break;
//
// ^id; - Set id
//
case '^': {
parseCode = UPDATED_OBJECT;
const char c = (char)istr.peek();
if (Common::isDigit(c)) {
int nId;
getIntFromStream(istr, nId);
setRefId(nId);
} else {
char szLocalBuff[256];
szLocalBuff[0] = 0;
CBofString s(szLocalBuff, 256);
getAlphaNumFromStream(istr, s);
setRefName(s);
}
break;
}
//
// *state; - Set state
//
case '*': {
parseCode = UPDATED_OBJECT;
int nState;
getIntFromStream(istr, nState);
setState(nState);
break;
}
//
// %cursor; - Set cursor
//
case '%': {
parseCode = UPDATED_OBJECT;
int nCursor;
getIntFromStream(istr, nCursor);
setOverCursor(nCursor);
break;
}
//
// [left,top,right,bottom] - Set position
//
case '[': {
parseCode = UPDATED_OBJECT;
CBofRect r;
istr.putBack();
getRectFromStream(istr, r);
setPosition(r.topLeft());
if (r.width() && r.height())
setSize(CBofSize(r.width(), r.height()));
break;
}
//
// IS [NOT] [MOVABLE|MODAL|VISIBLE|STRETCHABLE|HIGHLIGHT|ACTIVE|TRANSPARENT|HIDE_ON_CLICK|IMMEDIATE_RUN|LOCAL|CONSTANT_UPDATE|PRELOAD|FOREGROUND]
//
case 'I': {
if (istr.peek() != 'S') {
istr.putBack();
return parseCode;
}
char szLocalBuff[256];
szLocalBuff[0] = 0;
CBofString s(szLocalBuff, 256);
bool b = true;
istr.getCh();
istr.eatWhite();
getAlphaNumFromStream(istr, s);
if (!s.find("NOT")) {
getAlphaNumFromStream(istr, s);
istr.eatWhite();
b = false;
}
if (!s.find("MOVABLE")) {
setMovable(b);
} else if (!s.find("MODAL")) {
setModal(b);
} else if (!s.find("VISIBLE")) {
setVisible(b);
} else if (!s.find("STRETCHABLE")) {
setStretchable(b);
} else if (!s.find("HIGHLIGHT")) {
setHighlight(b);
} else if (!s.find("ACTIVE")) {
setActive(b);
} else if (!s.find("TRANSPARENT")) {
setTransparent(b);
} else if (!s.find("HIDE_ON_CLICK")) {
setHideOnClick(b);
} else if (!s.find("IMMEDIATE_RUN")) {
setImmediateRun(b);
} else if (!s.find("TIMELESS")) {
setTimeless(b);
} else if (!s.find("LOCAL")) {
setLocal(b);
} else if (!s.find("CONSTANT_UPDATE")) {
setConstantUpdate(b);
} else if (!s.find("PRELOAD")) {
setPreload(b);
} else if (!s.find("NOMENU")) {
_bNoMenu = true;
} else if (!s.find("FOREGROUND")) {
setForeGround(b);
} else {
putbackStringOnStream(istr, s);
if (!b)
putbackStringOnStream(istr, " NOT ");
putbackStringOnStream(istr, "IS ");
return parseCode;
}
parseCode = UPDATED_OBJECT;
break;
}
//
// ; is the end of the line, exit this object
//
case ';':
return PARSING_DONE;
//
// no match return from function
//
default:
istr.putBack();
return parseCode;
}
}
return parseCode;
}
void CBagObject::onLButtonUp(uint32 nFlags, CBofPoint */*xPoint*/, void *) {
if (getMenuPtr()) {
CBofPoint pt = getMousePos();
CBofWindow *pWnd = CBofApp::getApp()->getMainWindow();
pWnd->screenToClient(&pt);
// Just send the mouse pos
CBofRect r = getRect();
getMenuPtr()->trackPopupMenu(nFlags, pt.x, pt.y, pWnd, nullptr, &r);
} else {
g_noMenuFl = true;
}
runObject();
}
bool CBagObject::onMouseMove(uint32 /*nFlags*/, CBofPoint /*xPoint*/, void *) {
return false;
}
bool CBagObject::onMouseOver(uint32, CBofPoint, void *) {
return false;
}
CBofPoint CBagObject::getPosition() {
return CBofPoint(_nX, _nY);
}
int CBagObject::getRefId() {
return _nId;
}
int CBagObject::getOverCursor() {
return _nOverCursor;
}
int CBagObject::getState() {
return _nState;
}
CBofRect CBagObject::getRect() {
return CBofRect(_nX, _nY, _nX - 1, _nY - 1);
}
const CBofString &CBagObject::getFileName() {
return _sFileName;
}
CBagMenu *CBagObject::getMenuPtr() {
return _pMenu;
}
const CBofString &CBagObject::getRefName() {
if (_psName) {
return *_psName;
}
return _emptyString;
}
// Since we have an inordinate number of bag objects that replicate the
// filename as the objects name, if this is the case, then use a pointer
// to the filename.
void CBagObject::setRefName(const CBofString &s) {
// If we got an old one hanging around then trash it.
if (_psName && _psName != &_sFileName) {
delete _psName;
}
_psName = nullptr;
// If it's the same as the filename, then point to the filename
if (!_sFileName.isEmpty() && _sFileName.compare(s) == 0) {
_psName = &_sFileName;
} else if (!s.isEmpty()) {
_psName = new CBofString(s);
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,368 @@
/* 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 BAGEL_BAGLIB_OBJECT_H
#define BAGEL_BAGLIB_OBJECT_H
#include "bagel/spacebar/baglib/expression.h"
#include "bagel/spacebar/baglib/res.h"
#include "bagel/spacebar/boflib/gfx/bitmap.h"
#include "bagel/boflib/string.h"
#include "bagel/spacebar/baglib/parse_object.h"
namespace Bagel {
namespace SpaceBar {
class CBagObject;
typedef void *(*BagFuncPtr)(int, void *);
enum BagObjectType {
BASE_OBJ = 0x0000,
BMP_OBJ = BOF_BMP_OBJ,
SPRITE_OBJ = BOF_SPRITE_OBJ,
BUTTON_OBJ = BOF_BUTTON_OBJ,
SOUND_OBJ = BOF_SOUND_OBJ,
LINK_OBJ = BOF_LINK_OBJ,
TEXT_OBJ = BOF_TEXT_OBJ,
CHAR_OBJ = BOF_CHAR_OBJ,
VAR_OBJ = BOF_VAR_OBJ,
AREA_OBJ = BOF_AREA_OBJ,
EXPRESS_OBJ = BOF_EXPRESS_OBJ,
COMMAND_OBJ = BOF_COMM_OBJ,
MOVIE_OBJ = BOF_MOVIE_OBJ,
THING_OBJ = BOF_THING_OBJ,
RESPRNT_OBJ = BOF_RESPRNT_OBJ,
DOSSIER_OBJ = BOF_DOSSIER_OBJ,
USER_OBJ = 0x1000
};
enum BAG_OBJECT_PROPERTIES {
NONE = 0x0000,
MOVABLE = 0x0001,
MODAL = 0x0002,
VISIBLE = 0x0004,
HIGHLIGHT = 0x0008,
ACTIVE = 0x0010,
TRANSPAR = 0x0020,
HIDEONCLK = 0x0040,
IMRUN = 0x0080,
LOCAL = 0x0100,
NEGATIVE = 0x0200,
CONUPDATE = 0x0400,
STRETCH = 0x0800,
TIMELESS = 0x1000,
FLOATING = 0x2000,
PRELOAD = 0x4000,
FOREGROUND = 0x8000
};
class CBagMenu;
class CBagStorageDev;
CBofString getStringTypeOfObject(BagObjectType n);
/**
* CBofBagObject is an object that can be place within the slide window.
*/
class CBagObject : public CBagParseObject, public CBofObject, public CBofError {
private:
CBofString _sFileName; // File name contain object look/feel data
CBofString *_psName = nullptr; // Name of this object, needed by movable objects only, it equals file name unless specified.
CBagMenu *_pMenu = nullptr; // Menu for the object
CBagExpression *_pEvalExpr = nullptr; // Pointer to expression to be evaluated by
CBofString _emptyString;
int16 _nState = 0; // Current state of the object
uint16 _nId = 0; // Ref Id for an object
protected:
uint16 _xObjType = AREA_OBJ;
private:
uint16 _nProperties = 0; // Properties of object
int16 _nX = 0; // Replaces _xPosition
int16 _nY = 0;
byte _nOverCursor = 0; // Ref Id for the objects over cursor
byte _bDirty : 1; // Object needs redrawing or not?
byte _bMsgWaiting : 1; // Event needing to be played?
byte _bAlwaysUpdate : 1; // For message light
byte _bNoMenu : 1; // Used by AS NOMENU
protected:
byte _bInteractive = 0;
// Object property functionality
bool isProperty(BAG_OBJECT_PROPERTIES xProp) {
return _nProperties & xProp;
}
void setProperty(BAG_OBJECT_PROPERTIES xProp, bool bVal);
public:
CBagObject();
virtual ~CBagObject();
bool isInteractive() {
return _bInteractive;
}
void setInteractive(bool b) {
_bInteractive = (byte)b;
}
// Callback function functionality - probably can be phased out
virtual bool runCallBack() {
return false;
}
virtual BagFuncPtr getCallBack() {
return nullptr;
}
// Run Object is called when there is no callback and the item was selected
virtual bool runObject();
void setExpression(CBagExpression *pExpr) {
_pEvalExpr = pExpr;
}
CBagExpression *getExpression() const {
return _pEvalExpr;
}
// Return true if the Object had members that are properly initialized/de-initialized
ErrorCode attach() override;
ErrorCode detach() override;
BagObjectType getType() {
return (BagObjectType)_xObjType;
}
void setType(BagObjectType nType) {
_xObjType = (uint16)nType;
}
// Object can be moved within a screen
virtual bool isInside(const CBofPoint &xPoint) {
return getRect().ptInRect(xPoint);
}
// Object can be moved within a screen
bool isMovable() {
return isProperty(MOVABLE);
}
void setMovable(bool b = true) {
setProperty(MOVABLE, b);
}
// Object can be stretched within a screen
bool isStretchable() {
return isProperty(STRETCH);
}
void setStretchable(bool b = true) {
setProperty(STRETCH, b);
}
// Object has exclusive updates to a screen
bool isModal() {
return isProperty(MODAL);
}
void setModal(bool b = true) {
setProperty(MODAL, b);
}
virtual bool isModalDone() {
return true;
}
// Is object visible within scene
bool isVisible() {
return isProperty(VISIBLE);
}
void setVisible(bool b = true) {
setProperty(VISIBLE, b);
}
// Should object be highlighted when the mouse is over
bool isHighlight() {
return isProperty(HIGHLIGHT);
}
void setHighlight(bool b = true) {
setProperty(HIGHLIGHT, b);
}
// Is the object active in this world
bool isActive() {
return isProperty(ACTIVE);
}
void setActive(bool b = true) {
setProperty(ACTIVE, b);
}
// Is the object has a transparent background
bool isTransparent() {
return isProperty(TRANSPAR);
}
virtual void setTransparent(bool b = true) {
setProperty(TRANSPAR, b);
}
// Should the object be hidden when clicked on
bool isHideOnClick() {
return isProperty(HIDEONCLK);
}
void setHideOnClick(bool b = true) {
setProperty(HIDEONCLK, b);
}
// Should the object run and then be destroyed after the attach
bool isImmediateRun() {
return isProperty(IMRUN);
}
void setImmediateRun(bool b = true) {
setProperty(IMRUN, b);
}
// Is the object currently local to the object
bool isLocal() {
return isProperty(LOCAL);
}
void setLocal(bool b = true) {
setProperty(LOCAL, b);
}
// Is the object expression negative
bool isNegative() {
return isProperty(NEGATIVE);
}
void setNegative(bool b = true) {
setProperty(NEGATIVE, b);
}
// Should the object be constantly updated, even when not on screen
bool isConstantUpdate() {
return isProperty(CONUPDATE);
}
void setConstantUpdate(bool b = true) {
setProperty(CONUPDATE, b);
}
// Does this objects action take up time
bool isTimeless() {
return isProperty(TIMELESS);
}
void setTimeless(bool b = true);
// Does this objects have a set position/or should the sdev provide one when it is attached
bool isFloating() {
return isProperty(FLOATING);
}
void setFloating(bool b = true) {
setProperty(FLOATING, b);
}
// Does this objects have a set position/or should the sdev provide one when it is attached
bool isPreload() {
return isProperty(PRELOAD);
}
void setPreload(bool b = true) {
setProperty(PRELOAD, b);
}
// Does this objects have a set position/or should the sdev provide one when it is attached
bool isForeGround();
void setForeGround(bool b = true);
int getProperties();
void setProperties(int nProperties);
// Init variables
virtual const CBofString *getInitInfo() const;
virtual void setInitInfo(const CBofString &) {
}
virtual int getProperty(const CBofString &sProp);
virtual void setProperty(const CBofString &, int nVal);
bool isDirty() {
return _bDirty != 0;
}
void setDirty(bool b = true) {
_bDirty = (byte)b;
}
// If this thing is getting purged but is awaiting playback, then mark it as such.
bool isMsgWaiting() {
return _bMsgWaiting != 0;
}
void setMsgWaiting(bool b = true) {
_bMsgWaiting = (byte)b;
}
bool isAlwaysUpdate() {
return _bAlwaysUpdate != 0;
}
void setAlwaysUpdate(bool b = true) {
_bAlwaysUpdate = (byte)b;
}
bool isNoMenu() {
return _bNoMenu;
}
void setNoMenu(bool b = true) {
_bNoMenu = (byte)b;
}
virtual CBofPoint getPosition();
virtual int getRefId();
virtual int getOverCursor();
virtual int getState();
virtual CBofRect getRect();
virtual const CBofString &getFileName();
CBagMenu *getMenuPtr();
virtual const CBofString &getRefName();
virtual void setRefName(const CBofString &s);
virtual void setFileName(const CBofString &s);
virtual void setSize(const CBofSize &) {
}
virtual void setRefId(int id);
virtual void setOverCursor(int curs);
virtual void setState(int state);
virtual void setMenuPtr(CBagMenu *pm);
virtual void setPosition(const CBofPoint &pos);
/**
* Takes in info and then removes the relative information and returns
* UNKNOWN_TOKEN if nothing has changed
* UPDATED_OBJECT if something has changed
* PARSING_DONE if done processing
*/
ParseCodes setInfo(CBagIfstream &istr) override;
virtual ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect = nullptr, int /*nMaskColor*/ = -1);
virtual bool onObjInteraction(CBagObject * /*pObj*/, CBagStorageDev * /*pSDev*/);
virtual void onLButtonDown(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr) {
}
virtual void onLButtonUp(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr); // run menu if available
virtual bool onMouseMove(uint32 /*nFlags*/, CBofPoint /*xPoint*/, void * = nullptr);
virtual bool onMouseOver(uint32 /*nFlags*/, CBofPoint /*xPoint*/, void * = nullptr);
};
inline void CBagObject::setFileName(const CBofString &s) {
_sFileName = s;
}
inline void CBagObject::setMenuPtr(CBagMenu *pm) {
_pMenu = pm;
}
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,58 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/paint_table.h"
namespace Bagel {
namespace SpaceBar {
stripEnds STRIP_POINTS[153][120];
void PaintTable::initialize(Common::SeekableReadStream &src) {
for (int stripNum = 0; stripNum < 153; ++stripNum) {
// Read comment line
Common::String line = src.readLine();
assert(line.hasPrefix("/*"));
// Iterate through the following 12 lines to read the 120 points
int pointIndex = 0;
for (int lineNum = 0; lineNum < 12; ++lineNum) {
line = src.readLine();
for (int pointNum = 0; pointNum < 10; ++pointNum, ++pointIndex) {
// Get the point
int y1 = 0, y2 = 0;
const int result = sscanf(line.c_str(), "{ %d,%d}", &y1, &y2);
assert(result == 2);
STRIP_POINTS[stripNum][pointIndex]._top = y1;
STRIP_POINTS[stripNum][pointIndex]._bottom = y2;
// Move to next point on line
line = Common::String(strchr(line.c_str() + 1, '{'));
}
}
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,49 @@
/* 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 BAGEL_BAGLIB_PAINT_TABLE_H
#define BAGEL_BAGLIB_PAINT_TABLE_H
#include "common/stream.h"
namespace Bagel {
namespace SpaceBar {
struct stripEnds {
int16 _top;
int16 _bottom;
};
extern stripEnds STRIP_POINTS[153][120];
class PaintTable {
public:
/**
* Loads the data used for the pseudo-3d projection of panning windows
*/
static void initialize(Common::SeekableReadStream &src);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,435 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 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/>.
*
*/
#include "bagel/spacebar/baglib/pan_bitmap.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/paint_table.h"
namespace Bagel {
namespace SpaceBar {
const CBofRect CBagPanBitmap::getMaxView(CBofSize s) {
CBofRect r;
if (_bPanorama) {
int h = 3 * (int)((double)width() / (MAX_DIV_VIEW * 4));
if (h > height())
h = height();
r.setRect(0, 0, (int)(width() / MAX_DIV_VIEW - 2), h - 1);
} else {
r.setRect(0, 0, width() - 1, height() - 1);
}
if (s.cx > 0 && r.right > s.cx) {
// r.left = s.cx;
r.right = s.cx - 1;
}
if (s.cy > 0 && r.bottom > s.cy) {
r.bottom = s.cy - 1;
}
return r;
}
CBagPanBitmap::CBagPanBitmap(const char *pszFileName, CBofPalette *pPalette, const CBofRect &xViewSize) :
CBofBitmap(pszFileName, pPalette, true) {
int nW = width();
int nH = height();
_bPanorama = false;
_pCosineTable = nullptr;
_bActiveScrolling = false; // The scrolling is not active
_xDirection = kDirNONE; // Direction is not moving
_xFOVAngle = 0;
_nCorrWidth = 0;
_nNumDegrees = 0;
if (nW && nH) {
CBofRect xMaxViewSize(0, 0, nW - 1, nH - 1);
if (nW > 1000) {
xMaxViewSize.left = (long)(nW / MAX_DIV_VIEW);
_bPanorama = true;
}
pPalette = getPalette();
if (xViewSize.isRectEmpty())
_xCurrView = xMaxViewSize;
else
_xCurrView = xViewSize;
if (_xCurrView.width() > xMaxViewSize.width()) {
_xCurrView.setRect(0, _xCurrView.top, xMaxViewSize.width() - 1, _xCurrView.bottom);
}
_xRotateRate.x = (nW - _xCurrView.width()) / 64 + 1;
_xRotateRate.y = (nH - _xCurrView.height()) / 64 + 1;
normalizeViewSize();
// If FOV is set to 0 then unity FOV is assumed (faster redraws)
// The update parameter is set to false to avoid to update the cosine table as _nCorrWidth isn't set yet
setFOV(DEF_FOV, false);
// Initialize _nCorrWidth and generate the cosine table.
if (_bPanorama)
setCorrWidth(4, true);
else
setCorrWidth(0, true);
_bIsValid = true;
return;
}
_bIsValid = false;
}
CBagPanBitmap::~CBagPanBitmap() {
assert(isValidObject(this));
delete[] _pCosineTable;
_pCosineTable = nullptr;
}
// This must be updated whenever the size, view size, or correction width changes
void CBagPanBitmap::generateCosineTable() {
int nWidth = 1 << _nCorrWidth;
int offset = nWidth >> 1; // This is not really needed just more correction to move angle to center
int viewWidth = _xCurrView.width();
_nNumDegrees = (viewWidth >> _nCorrWidth) + 1;
delete[] _pCosineTable;
_pCosineTable = new CBofFixed[_nNumDegrees];
for (int i = 0; i < _nNumDegrees; i++) {
double inArea = (double)(offset + i * nWidth) / viewWidth;
_pCosineTable[i] = (CBofFixed)(cos(_xFOVAngle * (-1.0 + 2.0 * inArea)));
}
}
CBofRect CBagPanBitmap::getWarpSrcRect() {
int nH2 = height() >> 1;
return CBofRect(_xCurrView.left,
nH2 + (int)(*_pCosineTable * CBofFixed(_xCurrView.top - nH2)),
_xCurrView.right,
nH2 + (int)(*_pCosineTable * CBofFixed(_xCurrView.bottom - nH2)));
}
CBofPoint CBagPanBitmap::warpedPoint(CBofPoint &xPoint) {
CBofRect r = getRect();
int nH2 = height() >> 1;
int nW = width();
int nWidth = 1 << _nCorrWidth; // It may no longer be necessary to store corr width as a shift arg
int nCenter = r.top + nH2;
int nOffset = (xPoint.x - _xCurrView.left); // nWidth;
if (nOffset < 0)
nOffset += nW;
nOffset /= nWidth;
if ((nOffset < 0) || ((xPoint.x - _xCurrView.left) > _xCurrView.width()) || (nOffset >= _nNumDegrees))
return CBofPoint(0, 0);
CBofFixed srcHeight = _pCosineTable[nOffset];
return CBofPoint(xPoint.x, nCenter + (int)(srcHeight * CBofFixed(xPoint.y - nH2)));
}
ErrorCode CBagPanBitmap::paintWarped(CBofBitmap *pBmp, const CBofRect &dstRect, const CBofRect &srcRect, const int offset, CBofBitmap *pSrcBmp, const CBofRect &preSrcRect) {
int nH2 = _nDY >> 1;
int nWidth = 1 << _nCorrWidth; // It may no longer be necessary to store corr width as a shift arg
CBofFixed *pSrcHeight = &_pCosineTable[offset >> _nCorrWidth];
CBofFixed srcTop = preSrcRect.top + srcRect.top - nH2;
CBofFixed srcBottom = preSrcRect.top + srcRect.bottom - nH2;
int nCenter = nH2;
int nTop = nCenter - preSrcRect.top;
int nRight = (srcRect.left + nWidth) - 1;
CBofRect PanSrcRect;
CBofRect WndDstRect(dstRect.left + 0, dstRect.top, (dstRect.left + 0 + nWidth) - 1, dstRect.bottom);
pBmp->lock();
pSrcBmp->lock();
int nIncrement = 1;
if (nWidth < 4) {
for (int i = 0; i < dstRect.width(); i += nWidth) {
// Set the source
//
PanSrcRect.setRect(srcRect.left + i,
nTop + (int)(*pSrcHeight * srcTop),
nRight + i,
nTop + (int)(*pSrcHeight * srcBottom));
pSrcBmp->paint(pBmp, &WndDstRect, &PanSrcRect);
WndDstRect.left = WndDstRect.right + 1;
WndDstRect.right = WndDstRect.right + nWidth;
pSrcHeight += nIncrement;
}
} else if (nWidth == 4) {
int tableSlot = srcRect.top + preSrcRect.top;
int stripNumber = 0;
for (int i = 0; i < dstRect.width(); i += nWidth, stripNumber++) {
// Set the source
PanSrcRect.setRect(srcRect.left + i,
STRIP_POINTS[tableSlot][stripNumber]._top,
nRight + i,
STRIP_POINTS[tableSlot][stripNumber]._bottom);
pSrcBmp->paintStretch4(pBmp, &WndDstRect, &PanSrcRect);
WndDstRect.left = WndDstRect.right + 1;
WndDstRect.right = WndDstRect.right + nWidth;
}
} else { // nWidth > 4
for (int i = 0; i < dstRect.width(); i += nWidth) {
// Set the source
PanSrcRect.setRect(srcRect.left + i,
nTop + (int)(*pSrcHeight * srcTop),
nRight + i,
nTop + (int)(*pSrcHeight * srcBottom));
pSrcBmp->paintStretchOpt(pBmp, &WndDstRect, &PanSrcRect, nWidth);
WndDstRect.left = WndDstRect.right + 1;
WndDstRect.right = WndDstRect.right + nWidth;
pSrcHeight += nIncrement;
}
}
pSrcBmp->unlock();
pBmp->unlock();
return _errCode;
}
ErrorCode CBagPanBitmap::paintUncorrected(CBofBitmap *pBmp, CBofRect &dstRect) {
int tmp = _nCorrWidth;
_nCorrWidth = 0;
CBofFixed fONE(1);
CBofFixed fH2(height() / 2);
CBofFixed fCos(_pCosineTable[0]);
int nOffset = (int)((fONE - fCos) * fH2);
dstRect = getCurrView();
CBofRect tmpRect = dstRect;
dstRect.top -= nOffset;
dstRect.bottom += nOffset;
if (dstRect.top < 0) {
dstRect.bottom = dstRect.height() - 1;
dstRect.top = 0;
}
if (dstRect.height() >= pBmp->height()) {
dstRect.bottom = dstRect.top + pBmp->height() - 2;
}
_xCurrView = dstRect;
paint(pBmp);
_xCurrView = tmpRect;
_nCorrWidth = tmp;
return _errCode;
}
ErrorCode CBagPanBitmap::paint(CBofBitmap *pBmp, const CBofPoint xDstOffset) {
CBofRect dstRect;
CBofRect srcRect = _xCurrView;
int nW = width();
int viewWidth = _xCurrView.width();
srcRect.right = _xCurrView.left + viewWidth - 1;
int nOffset = srcRect.right - nW;
dstRect.top = xDstOffset.y;
dstRect.bottom = dstRect.top + srcRect.height() - 1;
// If the right side of the view is the beginning of the panorama
// paint the un-wrapped side (right) first.
dstRect.left = xDstOffset.x;
dstRect.right = xDstOffset.x + viewWidth - 1;
if (nOffset > 0) {
CBofRect srcRect2 = srcRect;
srcRect2.left = 0;
srcRect2.right = nOffset;
dstRect.right = xDstOffset.x + viewWidth - 1;
dstRect.left = dstRect.right - nOffset;
CBofBitmap::paint(pBmp, &dstRect, &srcRect2);
srcRect.right = nW - 1;
dstRect.right = dstRect.left;
dstRect.left = xDstOffset.x;
}
CBofBitmap::paint(pBmp, &dstRect, &srcRect);
return _errCode;
}
CBagPanBitmap::Direction CBagPanBitmap::updateView() {
if (_bActiveScrolling) {
if (_xDirection & kDirLEFT)
rotateRight();
else if (_xDirection & kDirRIGHT)
rotateLeft();
if (_xDirection & kDirUP)
rotateUp();
else if (_xDirection & kDirDOWN)
rotateDown();
return _xDirection;
}
return kDirNONE;
}
void CBagPanBitmap::setCorrWidth(int nWidth, bool bUpdate) {
int i = 0;
while (nWidth >>= 1)
++i;
if (i < 6) {
_nCorrWidth = i;
if (bUpdate) {
generateCosineTable();
}
}
}
void CBagPanBitmap::rotateRight(int nXRotRate) {
if (nXRotRate > 0)
offsetCurrView(CBofPoint(nXRotRate, 0));
else
offsetCurrView(CBofPoint(_xRotateRate.x, 0));
}
void CBagPanBitmap::rotateLeft(int nXRotRate) {
if (nXRotRate > 0)
offsetCurrView(CBofPoint(-1 * nXRotRate, 0));
else
offsetCurrView(CBofPoint(-1 * _xRotateRate.x, 0));
}
void CBagPanBitmap::rotateUp(int nYRotRate) {
if (nYRotRate > 0)
offsetCurrView(CBofPoint(0, nYRotRate));
else
offsetCurrView(CBofPoint(0, _xRotateRate.y));
}
void CBagPanBitmap::rotateDown(int nYRotRate) {
if (nYRotRate > 0)
offsetCurrView(CBofPoint(0, -1 * nYRotRate));
else
offsetCurrView(CBofPoint(0, -1 * _xRotateRate.y));
}
void CBagPanBitmap::normalizeViewSize() {
int nW = width();
int nH = height();
if (_bPanorama) {
// The CurrView can not be more than 0.25Width x Height of the Bitmap
if ((_xCurrView.width() >= nW / MAX_DIV_VIEW) || (_xCurrView.width() <= 0))
_xCurrView.right = (long)(_xCurrView.left + nW / MAX_DIV_VIEW - 1);
if ((_xCurrView.height() >= nH) || (_xCurrView.height() <= 0))
_xCurrView.bottom = _xCurrView.top + nH - 1;
// The Base coords of CurrView must exist within the rectangle
while (_xCurrView.left < 0)
_xCurrView.offsetRect(nW, 0);
while (_xCurrView.left >= nW)
_xCurrView.offsetRect(-1 * nW, 0);
} else { // Not a panorama
// The Base coords of CurrView must exist within the rectangle
if (_xCurrView.left < 0)
_xCurrView.offsetRect(-_xCurrView.left, 0);
else if (_xCurrView.right > nW)
_xCurrView.offsetRect(nW - _xCurrView.right, 0);
}
// We never have up and down wrap around
if (_xCurrView.top < 0)
_xCurrView.offsetRect(0, -_xCurrView.top);
if (_xCurrView.bottom >= nH)
_xCurrView.offsetRect(0, (nH - _xCurrView.bottom) - 1);
}
void CBagPanBitmap::setCurrView(const CBofRect &xCurrView) {
_xCurrView = xCurrView;
normalizeViewSize();
}
void CBagPanBitmap::offsetCurrView(const CBofPoint &xOffset) {
CBofRect xCurrView = _xCurrView;
xCurrView.offsetRect(xOffset);
setCurrView(xCurrView);
}
void CBagPanBitmap::setFOV(double degrees, bool bUpdate) {
_xFOVAngle = degrees / 114.5916558176;
if (bUpdate) {
generateCosineTable();
}
}
void CBagPanBitmap::setViewSize(const CBofSize &xViewSize, bool bUpdate) {
_xCurrView.right = _xCurrView.left + xViewSize.cx;
_xCurrView.bottom = _xCurrView.top + xViewSize.cy;
normalizeViewSize();
if (bUpdate) {
generateCosineTable();
}
}
CBofSize CBagPanBitmap::setUnityViewSize() {
int w = (int)(width() * _xFOVAngle / 3.14159);
_xCurrView.setRect(0, _xCurrView.top, w, _xCurrView.bottom);
generateCosineTable();
return getViewSize();
}
double CBagPanBitmap::setUnityFOV() {
setFOV(360.0 * _xCurrView.width() / width(), false); // If FOV is set to 0 then unity FOV is assumed (faster redraws)
generateCosineTable();
return getFOV();
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,134 @@
/* 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 BAGEL_BAGLIB_PAN_BITMAP_H
#define BAGEL_BAGLIB_PAN_BITMAP_H
#include "bagel/spacebar/boflib/gfx/bitmap.h"
#include "bagel/spacebar/boflib/fixed.h"
namespace Bagel {
namespace SpaceBar {
#define MAX_DIV_VIEW (12.8 / 3) // Ratio for 480x380 Screen
#define DEF_FOV (360 / MAX_DIV_VIEW) // 1TO1 Paint FOV
class CBagPanBitmap : public CBofBitmap {
public:
enum Direction {
kDirNONE = 0x0,
kDirUP = 0x01,
kDirDOWN = 0x02,
kDirLEFT = 0x04,
kDirRIGHT = 0x08,
kDirVIEW = 0x10
};
private:
CBofRect _xCurrView; // Viewport Window size (0->Width-1,0->Height-1,1->Width+Width/4,1->Height)
double _xFOVAngle; // Field of view in radians
CBofPoint _xRotateRate; // Rate of rotation on increment left, right ...
bool _bActiveScrolling; // True when there should be screen updates
bool _bPanorama; // True when the bitmap is a 360 panorama
Direction _xDirection; // Set direction for next update
int _nCorrWidth; // Size of each correction band
CBofFixed *_pCosineTable; // Lookup table for cosine values
int _nNumDegrees; // Number of lookups in the cosine table
bool _bIsValid; // Is the bmp a valid object
void normalizeViewSize();
void generateCosineTable();
public:
CBagPanBitmap(const char *pszFileName, CBofPalette *pPalette, const CBofRect &xViewSize = CBofRect());
virtual ~CBagPanBitmap();
bool isValid() const {
return _bIsValid;
}
bool isPan() const {
return _bPanorama;
}
ErrorCode paint(CBofBitmap *pBmp, CBofPoint xDstOffset = CBofPoint(0, 0));
ErrorCode paintUncorrected(CBofBitmap *pBmp, CBofRect &dstRect);
ErrorCode paintWarped(CBofBitmap *pBmp, const CBofRect &dstRect, const CBofRect &srcRect, int offset = 0, CBofBitmap *pSrcBmp = nullptr, const CBofRect &preSrcRect = CBofRect());
CBofRect getWarpSrcRect();
CBofPoint warpedPoint(CBofPoint &xPoint);
const CBofRect getMaxView(CBofSize s = CBofSize(640, 480));
void setCorrWidth(int nWidth, bool bUpdate = true);
void rotateRight(int nXRotRate = 0);
void rotateLeft(int nXRotRate = 0);
void rotateUp(int nYRotRate = 0);
void rotateDown(int nYRotRate = 0);
Direction updateView();
void setCurrView(const CBofRect &xCurrView);
void offsetCurrView(const CBofPoint &xOffset);
void setFOV(double degrees, bool bUpdate = true);
void setViewSize(const CBofSize &xViewSize, bool bUpdate = true);
CBofSize setUnityViewSize();
double setUnityFOV();
double getFOV() const {
return _xFOVAngle;
}
const CBofSize getViewSize() const {
return CBofSize(_xCurrView.size());
}
const CBofRect getCurrView() const {
return _xCurrView;
}
Direction getDirection() const {
return _xDirection;
}
void setRotateRate(const CBofPoint &xRotRate) {
_xRotateRate = xRotRate;
}
void setDirection(const Direction xDirection) {
_xDirection = xDirection;
}
int getCorrWidth() {
return _nCorrWidth;
}
void activateScrolling(bool val = true) {
_bActiveScrolling = val;
}
void deActivateScrolling() {
activateScrolling(false);
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,883 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/spacebar/baglib/res.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/wield.h"
#include "bagel/spacebar/boflib/gfx/sprite.h"
#include "bagel/spacebar/baglib/button_object.h"
#include "bagel/spacebar/baglib/character_object.h"
#include "bagel/spacebar/baglib/text_object.h"
#include "bagel/spacebar/boflib/std_keys.h"
namespace Bagel {
namespace SpaceBar {
CBagPDA *CBagPanWindow::_pPDABmp; // Pointer to the PDA object
int CBagPanWindow::_nCorrection;
int CBagPanWindow::_nPanSpeed;
CBagWield *CBagPanWindow::_pWieldBmp; // Pointer to the WIELD object
void CBagPanWindow::initialize() {
_pPDABmp = nullptr;
_nCorrection = 4;
_nPanSpeed = 1;
_pWieldBmp = nullptr;
}
CBagPanWindow::CBagPanWindow() : CBagStorageDevWnd() {
_xViewPortPos = CBofPoint(0, 20);
_xMovementRect.setRectEmpty();
_nCorrection = CBagMasterWin::getCorrection();
_nPanSpeed = CBagMasterWin::getPanSpeed();
_pSlideBitmap = nullptr;
_pPalette = nullptr;
_bPaintToBackdrop = true;
_bStretchToScreen = false;
_bDraggingObject = false;
_bDraggingStart = CBofPoint(0, 0);
_pViewPortBitmap = nullptr;
// Objects to be painted to the window
_pFGObjectList = new CBofList<CBagObject *>();
// Declare this to be type game win, because it has a pda
_xSDevType = SDEV_GAMEWIN;
// Make sure the prefilter gets called.
setPreFilterPan(true);
CBagStorageDev::loadObjects();
}
CBofRect CBagPanWindow::unSetSlideBitmap() {
CBofRect viewRect;
setLActiveObject(nullptr);
if (_pSlideBitmap) {
viewRect = _pSlideBitmap->getCurrView();
delete _pSlideBitmap;
_pSlideBitmap = nullptr;
}
if (_pViewPortBitmap) {
delete _pViewPortBitmap;
_pViewPortBitmap = nullptr;
}
CBofSprite::closeLibrary();
// There is no palette right now
CBofApp::getApp()->setPalette(nullptr);
return viewRect;
}
CBofPalette *CBagPanWindow::setSlideBitmap(const CBofString &xSlideBmp, const CBofRect &xSlideRect) {
if (!xSlideBmp.isEmpty()) {
CBofRect viewRect = unSetSlideBitmap();
CBofRect cRect = getWindowRect();
if ((cRect.width() <= 0) || (cRect.width() > DEF_WIDTH))
cRect.setRect(cRect.left, cRect.top, cRect.left + DEF_WIDTH, cRect.bottom);
cRect.bottom = cRect.top + 3 * cRect.width() / 4 - 1;
if ((xSlideRect.width() <= 0) || (xSlideRect.width() > DEF_WIDTH))
viewRect.setRect(xSlideRect.left, xSlideRect.top, xSlideRect.left + DEF_WIDTH, DEF_HEIGHT);
else
viewRect = xSlideRect;
// Open Pan bitmap
_pSlideBitmap = new CBagPanBitmap(xSlideBmp, nullptr, viewRect);
// Make sure the file was found
if (!_pSlideBitmap->isValid()) {
_pPalette = nullptr;
reportError(ERR_FOPEN, "Unable to open file %s", xSlideBmp.getBuffer());
} else {
// Set the bagel crap
_pPalette = _pSlideBitmap->getPalette();
CBofApp::getApp()->setPalette(_pPalette);
CBagel::getBagApp()->getMasterWnd()->selectPalette(_pPalette);
CBofApp::getApp()->getMainWindow()->selectPalette(_pPalette);
selectPalette(_pPalette);
CBofSprite::openLibrary(_pPalette);
_pSlideBitmap->setCorrWidth(_nCorrection);
CBofBitmap *pBackDropBitmap = new CBofBitmap(DEF_WIDTH + 1, DEF_HEIGHT + 1, _pPalette);
if (pBackDropBitmap->height() <= 0 || pBackDropBitmap->width() <= 0) {
reportError(ERR_FOPEN, "Error opening bitmap");
}
_pViewPortBitmap = new CBofBitmap(DEF_WIDTH + 1, _pSlideBitmap->height() + 1, _pPalette);
if (!_pViewPortBitmap->height() || !_pViewPortBitmap->width()) {
reportError(ERR_FOPEN, "Error opening bitmap");
}
setBackdrop(pBackDropBitmap);
move(cRect.left, cRect.top);
}
}
return _pPalette;
}
CBagPanWindow::~CBagPanWindow() {
CBagStorageDev::releaseObjects(); // Delete all master sprite objects
if (_pSlideBitmap) {
delete _pSlideBitmap;
_pSlideBitmap = nullptr;
}
if (_pViewPortBitmap) {
delete _pViewPortBitmap;
_pViewPortBitmap = nullptr;
}
CBofSprite::closeLibrary(); // Free the off screen bitmap
delete _pFGObjectList;
}
void CBagPanWindow::onClose() {
CBagStorageDevWnd::onClose();
destroyWindow(); // Destruct the main window
}
ErrorCode CBagPanWindow::runModal(CBagObject *pObj) {
if (_pSlideBitmap != nullptr) {
_pSlideBitmap->updateView();
CBagStorageDevWnd::runModal(pObj);
// Make sure we update the entire screen after this,
// we're not really sure what got trashed, also,
// the cursor background will contain bogus information,
// so make sure that gets overwritten
setPreFilterPan(true);
}
return _errCode;
}
ErrorCode CBagPanWindow::onRender(CBofBitmap *pBmp, CBofRect *pRect) {
assert(isValidObject(this));
assert(pBmp != nullptr);
if (_pSlideBitmap != nullptr) {
_pSlideBitmap->updateView();
CBofRect dstRect(CBofPoint(0, 0), _pSlideBitmap->getViewSize());
CBofRect clientArea = getClientRect();
if (_pSlideBitmap->isPan()) {
// Paint uncorrected view to backdrop
CBofRect currViewRect = _pSlideBitmap->getCurrView(); // Hold current view
CBofRect offsetRect; // Size of viewportbmp
CBofRect srcRect = dstRect; // Src will be same as dst
// If we've been given the go ahead to call prefilter, then
// do so but don't do it again unless asked.
if (preFilterPan()) {
preFilter(pBmp, pRect, _pFGObjectList);
setPreFilterPan(false);
}
_pSlideBitmap->paintUncorrected(_pViewPortBitmap, offsetRect); // Paint and return size
srcRect.offsetRect(0, currViewRect.top - offsetRect.top); // less the offset from full
// Paint the objects to the backdrop
paintObjects(getObjectList(), _pViewPortBitmap, offsetRect, nullptr);
dstRect.offsetRect(_xViewPortPos);
// No correction ?
if (_nCorrection == 0) {
_pViewPortBitmap->paint(pBmp, &dstRect, &srcRect);
} else {
// Warp the backdrop to itself
_pSlideBitmap->paintWarped(pBmp, dstRect, srcRect, 0, _pViewPortBitmap, offsetRect);
}
if (isFiltered()) {
uint16 nFilterId = getFilterId();
(*_pBitmapFilter)(nFilterId, pBmp, pRect);
}
// Now paint it
paintObjects(_pFGObjectList, pBmp, clientArea, nullptr, false);
} else {
// Close-Ups
_pSlideBitmap->setCorrWidth(0, false);
// If we've been given the go ahead to call prefilter, then
// do so but don't do it again unless asked.
if (preFilterPan()) {
preFilter(pBmp, pRect, _pFGObjectList);
setPreFilterPan(false);
// Only paint the slide the first time around, if we paint
// it in subsequent calls, then we will trash our PDA in this closeup,
// and that will be a bad thing.
dstRect.offsetRect(_xViewPortPos);
((CBofBitmap *)_pSlideBitmap)->paint(pBmp, _xViewPortPos.x, _xViewPortPos.y);
}
clientArea.offsetRect(-_xViewPortPos.x, -_xViewPortPos.y);
paintObjects(getObjectList(), pBmp, clientArea, nullptr);
if (isFiltered()) {
uint16 nFilterId = getFilterId();
bool bFiltered = (*_pBitmapFilter)(nFilterId, pBmp, pRect);
if (bFiltered) {
setPreFilterPan(true);
}
}
// This must be changed so that the foreground objects are actually
// a list of child windows. The on paint message is then called with
// the background bitmap
paintObjects(_pFGObjectList, pBmp, clientArea, nullptr);
_pSlideBitmap->setCorrWidth(_nCorrection, false);
}
}
return _errCode;
}
ErrorCode CBagPanWindow::paintObjects(CBofList<CBagObject *> *list, CBofBitmap *pBmp, CBofRect &viewRect, CBofList<CBofRect> *pUpdateArea, bool tempVar) {
ErrorCode errorCode = ERR_NONE;
// can't use a null pointer
assert(pBmp != nullptr);
int nCount = list->getCount();
if (nCount != 0) {
int nW = _pSlideBitmap->width();
CBofPoint xCursorLocation = devPtToViewPort(*_xCursorLocation);
int nMouseOverObj = -1;
for (int i = 0; i < nCount; ++i) {
CBagObject *pObj = list->getNodeItem(i);
CBofRect xBmpRect = pObj->getRect();
// If it is a panorama we have to check for exceeded bounds
if (!pObj->isForeGround() && (nW > 1024) && (viewRect.right > nW) && (xBmpRect.left < (nW / 2)))
xBmpRect.offsetRect(nW, 0);
CBofRect xIntrRect;
if (xIntrRect.intersectRect(&viewRect, &xBmpRect) || pObj->isForeGround() || pObj->isModal()) {
CBofPoint pt = xBmpRect.topLeft();
if (!pObj->isForeGround()) {
pt = xBmpRect.topLeft() - viewRect.topLeft();
}
xIntrRect = xBmpRect;
xIntrRect.offsetRect(-xBmpRect.left, -xBmpRect.top);
// Only update dirty objects...
if (pObj->isDirty() || pObj->isAlwaysUpdate()) {
if (!(pObj->getType() == TEXT_OBJ && ((CBagTextObject *)pObj)->isCaption() && pObj->isImmediateRun())) {
pObj->update(pBmp, pt, &xIntrRect);
// If we're in a closeup and we have a character animation
// playing, then make sure we redraw
CBagCharacterObject *pCharObj = (CBagCharacterObject *)pObj;
// Only in closeups
if (!_pSlideBitmap->isPan() && pObj->getType() == CHAR_OBJ) {
// Handle non-modal movies also...
if (pCharObj->getNumberOfLoops() == 1) {
setPreFilterPan(true);
} else if (pObj->isAttached() && // don't care if it's not running...
(pCharObj->isStationary() == false) &&
(pCharObj->getNumberOfLoops() != 0) && // Plays multiple or infinite (fly == -1)
((pObj->getRect().width() != 480) &&
(pObj->getRect().height() != 360))) {
// Redraw everything inside of the closeup... but not the PDA...
// only want to redraw the closeup, not everything else.
//
// if our prefilter pan is already dirty, then don't mess with dirty
// object list.
bool b = preFilterPan();
setPreFilterPan(true);
if (!b) {
setDirtyAllObjects(false);
}
}
}
}
}
if (pUpdateArea) {
xIntrRect.offsetRect(pt);
pUpdateArea->addToTail(xIntrRect);
}
if (pObj->getRect().ptInRect(xCursorLocation)) {
pObj->onMouseOver(0, xCursorLocation, this);
nMouseOverObj = i;
}
} // if on screen
} // While a valid object
if ((nMouseOverObj < 0) && tempVar)
noObjectsUnderMouse();
}
return errorCode;
}
// Delete the foreground objects
void CBagPanWindow::deleteFGObjects() {
_pFGObjectList->removeAll();
}
ErrorCode CBagPanWindow::insertFGObjects(CBagObject *pBmp) {
// Can't use a nullptr pointer
assert(pBmp != nullptr);
_pFGObjectList->addToTail(pBmp);
return _errCode;
}
CBagObject *CBagPanWindow::getFGObjects(const CBofString &sObjName) {
int nListLen = _pFGObjectList->getCount();
for (int i = 0; i < nListLen; ++i) {
CBagObject *pObj = (*_pFGObjectList)[i];
if ((pObj->getRefName().find(sObjName)) != -1)
return pObj;
}
return nullptr;
}
void CBagPanWindow::activateView() {
if (_pSlideBitmap) {
_pSlideBitmap->activateScrolling();
_pSlideBitmap->setRotateRate(CBofPoint(32, 16));
}
}
void CBagPanWindow::deActivateView() {
if (_pSlideBitmap) {
_pSlideBitmap->deActivateScrolling();
}
}
void CBagPanWindow::enable() {
activateView();
}
void CBagPanWindow::disable() {
flushAllMessages();
deActivateView();
}
ErrorCode CBagPanWindow::onCursorUpdate(int nCurrObj) {
assert(isValidObject(this));
if (nCurrObj >= 0) {
CBagObject *pObj = getObjectByPos(nCurrObj);
if (pObj != nullptr)
CBagMasterWin::setActiveCursor(pObj->getOverCursor());
} else if (CBagWield::getWieldCursor() >= 0) {
CBagMasterWin::setActiveCursor(CBagWield::getWieldCursor());
}
return _errCode;
}
void CBagPanWindow::onKeyHit(uint32 lKey, uint32 lRepCount) {
assert(isValidObject(this));
if (_pSlideBitmap != nullptr) {
switch (lKey) {
case BKEY_MINUS:
if (_nCorrection == 0) {
_nCorrection = 64;
}
_nCorrection >>= 1;
_pSlideBitmap->setCorrWidth(_nCorrection);
CBagMasterWin::setCorrection(_nCorrection);
break;
case BKEY_PLUS:
if (_nCorrection == 0) {
_nCorrection = 1;
} else if ((_nCorrection <<= 1) > 32) {
_nCorrection = 0;
}
_pSlideBitmap->setCorrWidth(_nCorrection);
CBagMasterWin::setCorrection(_nCorrection);
break;
case BKEY_LEFT:
_pSlideBitmap->setRotateRate(CBofPoint(16, 8));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirRIGHT);
break;
case BKEY_RIGHT:
_pSlideBitmap->setRotateRate(CBofPoint(16, 8));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirLEFT);
break;
case BKEY_UP:
_pSlideBitmap->setRotateRate(CBofPoint(16, 8));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirDOWN);
break;
case BKEY_DOWN:
_pSlideBitmap->setRotateRate(CBofPoint(16, 8));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirUP);
break;
}
}
CBagStorageDevWnd::onKeyHit(lKey, lRepCount);
}
void CBagPanWindow::onMouseMove(uint32 nFlags, CBofPoint *p, void *) {
assert(isValidObject(this));
assert(p != nullptr);
CBofPoint xPoint = *p;
CBagStorageDevWnd::onMouseMove(nFlags, &xPoint);
if (!isCloseup()) {
if (_pSlideBitmap != nullptr) {
if (_cRightRect.ptInRect(xPoint)) {
_pSlideBitmap->setRotateRate(CBofPoint(((xPoint.x - _xMovementRect.right) * (_nPanSpeed + 1)) / 2, 0));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirLEFT);
CBagMasterWin::setActiveCursor(BOF_RT_CURSOR);
} else if (_cLeftRect.ptInRect(xPoint)) {
_pSlideBitmap->setRotateRate(CBofPoint(((_xMovementRect.left - xPoint.x) * (_nPanSpeed + 1)) / 2, 0));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirRIGHT);
CBagMasterWin::setActiveCursor(BOF_LT_CURSOR);
} else if (_cBottomRect.ptInRect(xPoint)) {
_pSlideBitmap->setRotateRate(CBofPoint(0, (xPoint.y - _xMovementRect.bottom)));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirUP);
CBagMasterWin::setActiveCursor(BOF_DN_CURSOR);
} else if (_cTopRect.ptInRect(xPoint)) {
_pSlideBitmap->setRotateRate(CBofPoint(0, (_xMovementRect.top - xPoint.y)));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirDOWN);
CBagMasterWin::setActiveCursor(BOF_UP_CURSOR);
} else {
_pSlideBitmap->setDirection(CBagPanBitmap::kDirNONE);
}
if (getLActiveObject() && getLActivity()) {
_pSlideBitmap->setDirection((CBagPanBitmap::Direction)(_pSlideBitmap->getDirection() | CBagPanBitmap::kDirVIEW));
}
}
}
// Change cursor based on the Foreground object list
// Run through background object list and find if the cursor is over an object
CBofList<CBagObject *> *pList = _pFGObjectList;
if (pList != nullptr) {
CBagObject *pOverObj = nullptr;
int nCount = pList->getCount();
for (int i = 0; i < nCount; ++i) {
CBagObject *pObj = pList->getNodeItem(i);
if (pObj->isInside(xPoint)) {
pOverObj = pObj;
}
}
// If we just happen to be over the pda then let our
// PDA code decide... oh, and we're wielding...
if (pOverObj != nullptr) {
int nCursorID = -1;
// the logz case is handled by onmousemove in zoompda
if (pOverObj->getRefName().find("BPDA_WLD") != -1) {
CBagPDA *pPda = (CBagPDA *)g_SDevManager->getStorageDevice(pOverObj->getRefName());
if (pPda != nullptr) {
CBofRect cRect = pOverObj->getRect();
nCursorID = pPda->getProperCursor(xPoint, cRect);
}
}
// Still no luck, if we're wielding, use that cursor.
if (nCursorID == -1) {
nCursorID = pOverObj->getOverCursor();
if (CBagWield::getWieldCursor() >= 0 && ((pOverObj->getRefName().find("BWIELD_WLD") != -1) || (pOverObj->getRefName().find("THUD_WLD") != -1))) {
nCursorID = CBagWield::getWieldCursor();
}
}
CBagMasterWin::setActiveCursor(nCursorID);
}
}
if (_bDraggingObject) {
CBagObject *pObj = _pFGObjectList->getNodeItem(_pFGObjectList->getCount() - 1);
pObj->setPosition(xPoint);
}
*_xCursorLocation = xPoint;
}
void CBagPanWindow::onLButtonDown(uint32 nFlags, CBofPoint *xPoint, void *) {
int nCount = _pFGObjectList->getCount();
if (nCount != 0) {
for (int i = 0; i < nCount; ++i) {
CBagObject *pObj = _pFGObjectList->getNodeItem(i);
if (pObj->isInside(*xPoint)) {
pObj->onLButtonDown(nFlags, xPoint, this);
return;
}
}
}
CBagStorageDevWnd::onLButtonDown(nFlags, xPoint);
MouseActivity nMA = getLActivity();
CBagObject *pActObj = getLActiveObject();
if (nMA && pActObj && pActObj->isMovable()) {
_bDraggingObject = true;
_bDraggingStart = pActObj->getPosition();
_pFGObjectList->addToTail(pActObj);
}
}
void CBagPanWindow::onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void *) {
MouseActivity nMA = getLActivity();
CBagObject *pActObj = getLActiveObject();
if ((pActObj != nullptr) && (nMA == kMouseDRAGGING) &&
(pActObj->getType() == BUTTON_OBJ) &&
(((CBagButtonObject *)pActObj)->getButtonType() == CBagButtonObject::BTN_SLIDER)) {
pActObj->onLButtonUp(nFlags, xPoint, this);
// We are not dragging a slider anymore
setLActivity(kMouseNONE);
setLActiveObject(nullptr);
} else {
bool bMoved = false;
if (_bDraggingObject) {
_bDraggingObject = false;
pActObj = _pFGObjectList->removeTail();
int nCount = _pFGObjectList->getCount();
if (nCount != 0) {
for (int i = 0; i < nCount; ++i) {
CBagObject *pObj = _pFGObjectList->getNodeItem(i);
CBofRect xBmpRect = pObj->getRect();
if (xBmpRect.ptInRect(*xPoint)) {
pObj->onObjInteraction(pActObj, this);
}
}
}
if (pActObj->getPosition() != _bDraggingStart) {
pActObj->setPosition(_bDraggingStart);
bMoved = true;
}
}
if (!bMoved) {
// Parse backwards to get topmost obj 1st
int nCount = _pFGObjectList->getCount();
if (nCount != 0) {
for (int i = nCount - 1; i >= 0; --i) {
CBagObject *pObj = _pFGObjectList->getNodeItem(i);
if (pObj->isInside(*xPoint)) {
pObj->onLButtonUp(nFlags, xPoint, this);
return;
}
}
}
}
CBagStorageDevWnd::onLButtonUp(nFlags, xPoint);
}
}
void CBagPanWindow::onSize(uint32 nType, int cx, int cy) {
// nRange defines the distance (in pixels) from a viewport edge
// (toward the center of the viewport) that the viewport boundary
// rectangles begin. The boundary rectangles surround the edges
// of the viewport. When the mouse cursor enters a boundary rectangle,
// it's time to pan the view. Larger positive values of nRange will
// cause the boundary rectangle to extend farther from the viewport edge.
// A value of zero will cause the boundary rectangles to be at the edge
// of the viewport. If nRange has a negative value, the boundary
// rectangle will start outside the viewport rectangle.
//
const int nRange = 16;
CBofRect xMaxPanBmpRect;
if (_pSlideBitmap)
xMaxPanBmpRect = _pSlideBitmap->getMaxView();
else
xMaxPanBmpRect.setRect(0, 0, DEF_WIDTH, DEF_HEIGHT);
CBofPoint vp;
CBofSize vs = CBofSize(cx, cy);
// Check if the current view is greater than the max view
if (vs.cx > xMaxPanBmpRect.width())
vs.cx = xMaxPanBmpRect.width();
if (_pSlideBitmap && _pSlideBitmap->width() > 480)
vs.cy = 3 * vs.cx / 4;
if (vs.cy > xMaxPanBmpRect.height())
vs.cy = xMaxPanBmpRect.height();
setViewPortSize(vs);
vp.x = (cx - vs.cx) / 2;
vp.y = 10;
setViewPortPos(vp);
vp.x += nRange;
vp.y += nRange;
vs.cx -= (2 * nRange); // Subtract 2*nRange from vs because there's
vs.cy -= (2 * nRange); // a boundary rectangle on the left and right
// *and* the top and bottom.
CBofRect cRect(vp, vs);
_cTopRect.setRect(cRect.left, 0, cRect.right, cRect.top);
_cBottomRect.setRect(cRect.left, cRect.bottom, cRect.right, 480 - 1);
_cLeftRect.setRect(0, cRect.top, cRect.left, cRect.bottom);
_cRightRect.setRect(cRect.right, cRect.top, 640 - 1, cRect.bottom);
setMovementRect(cRect);
}
void CBagPanWindow::OnWindowPosChanging(WindowPos *lpwndpos) {
const int MENUNBORDER = 50;
CBofRect xSlideBmpRect;
xSlideBmpRect.setRect(0, 0, DEF_WIDTH, DEF_HEIGHT);
if (lpwndpos->cx > xSlideBmpRect.width())
lpwndpos->cx = xSlideBmpRect.width();
if (lpwndpos->cy > xSlideBmpRect.height() + MENUNBORDER)
lpwndpos->cy = xSlideBmpRect.height() + MENUNBORDER;
}
void CBagPanWindow::flushInputEvents() {
g_system->getEventManager()->purgeKeyboardEvents();
g_system->getEventManager()->purgeMouseEvents();
}
#define PAN_WIDTH 2048
#define PAN_HEIGHT 512
#define HALF_PAN_WIDTH (PAN_WIDTH/2)
uint32 CBagPanWindow::rotateTo(CBofPoint &xPoint, int nRate) {
assert(nRate > 0);
if (_pSlideBitmap && (xPoint.x != -1) && (xPoint.y != -1)) {
CBofRect r = _pSlideBitmap->getCurrView();
for (;;) {
CBofPoint xCurrPos = r.topLeft();
int x = (xPoint.x - xCurrPos.x);
int y = (xPoint.y - xCurrPos.y);
if (abs(x) > HALF_PAN_WIDTH) {
if (x > 0) {
x -= PAN_WIDTH;
} else {
x += PAN_WIDTH;
}
}
// Are we there yet?
if (x == 0 && y == 0)
break;
int nRateX = MIN(x, nRate);
if (x < 0)
nRateX = MAX(x, -nRate);
int nRateY = MIN(y, nRate);
if (y < 0)
nRateY = MAX(y, -nRate);
r.offsetRect(nRateX, nRateY);
_pSlideBitmap->setCurrView(r);
paintScreen();
}
}
return 0;
}
uint32 CBagPanWindow::benchmark() {
deActivateView();
_pSlideBitmap->activateScrolling();
_pSlideBitmap->setRotateRate(CBofPoint(8, 0));
_pSlideBitmap->setDirection(CBagPanBitmap::kDirLEFT);
timerStart();
for (int i = 0; i < 50; i++)
paintScreen();
uint32 dTime = timerStop();
activateView();
return dTime;
}
bool CBagPanWindow::deactivatePDA() {
// If we have a PDA and the pda is active
if (_pPDABmp && _pPDABmp->isActivated()) {
// deactivate it
_pPDABmp->deactivate();
// PDA successfully deactivated
return true;
}
// PDA already deactivated
return false;
}
bool CBagPanWindow::activatePDA() {
// If we have a BMP and the pda is not active
if (_pPDABmp && (!_pPDABmp->isActivated() || _pPDABmp->isActivating())) {
_pPDABmp->activate(); // activate it
// PDA successfully activated
return true;
}
// PDA already activated
return false;
}
const CBofPoint CBagPanWindow::devPtToViewPort(const CBofPoint &xPoint) {
CBofRect r = _pSlideBitmap->getCurrView();
CBofPoint p;
p.x = xPoint.x + r.left - _xViewPortPos.x;
p.y = xPoint.y + r.top - _xViewPortPos.y;
if (_pSlideBitmap->isPan()) {
if (p.x >= _pSlideBitmap->width())
p.x -= _pSlideBitmap->width();
// If this view is being painted with a correction, we need
// to correct the point to the warped view space.
if (_nCorrection != 0) {
p = _pSlideBitmap->warpedPoint(p);
}
}
return p;
}
const CBofPoint CBagPanWindow::viewPortToDevPt(const CBofPoint &xPoint) {
CBofRect r = _pSlideBitmap->getCurrView();
CBofPoint p(xPoint.x - r.left, xPoint.y - r.top);
if (p.x < 0)
p.x += _pSlideBitmap->width();
return p;
}
ErrorCode CBagPanWindow::attachActiveObjects() {
CBagStorageDev::attachActiveObjects();
if (_pPDABmp != nullptr) {
_pPDABmp->attachActiveObjects();
}
return _errCode;
}
void CBagPanWindow::setViewPortSize(const CBofSize &xViewSize) {
if (_pSlideBitmap)
_pSlideBitmap->setViewSize(xViewSize);
}
const CBofRect CBagPanWindow::getViewPort() {
CBofRect r;
if (_pSlideBitmap)
r = _pSlideBitmap->getCurrView();
return r;
}
const CBofSize CBagPanWindow::getViewPortSize() {
CBofRect r;
if (_pSlideBitmap)
r = _pSlideBitmap->getCurrView();
return r.size();
}
void CBagPanWindow::waitForPDA() {
// Make sure we have a non-null pda
while (_pPDABmp && _pPDABmp->isActivating()) {
setPreFilterPan(true);
_pPDABmp->setDirty(true);
paintScreen();
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,220 @@
/* 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 BAGEL_BAGLIB_PAN_WINDOW_H
#define BAGEL_BAGLIB_PAN_WINDOW_H
#include "bagel/spacebar/baglib/pda.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/baglib/wield.h"
#include "bagel/spacebar/baglib/pan_bitmap.h"
#include "bagel/boflib/stdinc.h"
namespace Bagel {
namespace SpaceBar {
#define BOFCURS 1
#define DEF_WIDTH 639
#define DEF_HEIGHT 479
#define EVAL_EXPR 303
// The height and width of the pan area
#define PAN_AREA_WIDTH 480
#define PAN_AREA_HEIGHT 360
//
// CBagPanWindow -
// CBagPanWindow is a window that contains a slide bitmap object. It has specialize
// functions for handling slide bitmaps and slide objects.
//
class CBagPanWindow : public CBagStorageDevWnd {
private:
static int _nCorrection;
static int _nPanSpeed;
//
// private data members
//
CBofPoint _xViewPortPos; // Position of the viewport
CBofRect _xMovementRect; // if mouse is in this region will not scroll
CBofRect _cLeftRect;
CBofRect _cRightRect;
CBofRect _cTopRect;
CBofRect _cBottomRect;
CBagPanBitmap *_pSlideBitmap; // Contains the full bitmap of the world
CBofBitmap *_pViewPortBitmap; // Contains the current viewport bitmap
CBofPalette *_pPalette;
CBofPoint _bDraggingStart; // Starting location of the dragged object
bool _bDraggingObject; // Whether or not the first FG object is being dragged
bool _bStretchToScreen; // Whether or not the backdrop is painted full screen
bool _bPaintToBackdrop; // Whether or not the backdrop is a extra paint surface
CBofList<CBagObject *> *_pFGObjectList; // Objects to be painted to the window
public:
static CBagWield *_pWieldBmp; // Pointer to the WIELD object
CBagPanWindow();
virtual ~CBagPanWindow();
static void initialize();
ErrorCode attachActiveObjects() override;
ErrorCode onRender(CBofBitmap *pBmp, CBofRect *pRect = nullptr) override;
/**
* The modal object is painted to the screen until it is done with
* its modal loop. This is mainly used with characters. It is called
* when the loop value of a modal character is set, before execution
* of the next line of script.
*/
ErrorCode runModal(CBagObject *pObj) override;
ErrorCode insertFGObjects(CBagObject *pBmp);
void deleteFGObjects();
CBagObject *getFGObjects(const CBofString &sObjName);
CBofPalette *setSlideBitmap(const CBofString &xSlideBmp, const CBofRect &xSlideRect = CBofRect(0, 0, 0, 0));
/**
* Clear the last pan bitmaps and return a rect of the current view
*/
CBofRect unSetSlideBitmap();
uint32 rotateTo(CBofPoint &xPoint, int nRate = 8);
void activateView();
void deActivateView();
void enable() override;
void disable() override;
ErrorCode paintObjects(CBofList<CBagObject *> *list, CBofBitmap *pBmp, CBofRect &viewOffsetRect,
CBofList<CBofRect> * = nullptr, bool tempVar = true) override;
const CBofPoint devPtToViewPort(const CBofPoint &xPoint) override;
const CBofPoint viewPortToDevPt(const CBofPoint &xPoint) override;
void setViewPortSize(const CBofSize &xViewSize);
const CBofRect getViewPort();
const CBofSize getViewPortSize();
CBagPanBitmap *getSlideBitmap() const {
return _pSlideBitmap;
}
void setViewPortPos(const CBofPoint &pos) {
_xViewPortPos = pos; // Position of the viewport
}
static void setPanSpeed(int nSpeed) {
_nPanSpeed = nSpeed;
}
static int getPanSpeed() {
return _nPanSpeed;
}
const CBofPoint getViewPortPos() {
return _xViewPortPos;
}
const CBofRect getMaxView() {
return _pSlideBitmap->getMaxView();
}
void setMovementRect(const CBofRect &rect) {
_xMovementRect = rect;
}
const CBofRect &getMovementRect() {
return _xMovementRect;
}
void setPaintToBackdrop(const bool bPaint) {
_bPaintToBackdrop = bPaint;
}
bool getStretchToScreen() {
return _bStretchToScreen;
}
bool setStretchToScreen(bool val = true) {
return _bStretchToScreen = val;
}
static int getRealCorrection() {
return _nCorrection;
}
static void setRealCorrection(int n) {
_nCorrection = n;
}
int getCorrection() {
return _pSlideBitmap->getCorrWidth();
}
void setCorrection(int nCorr) {
_pSlideBitmap->setCorrWidth(nCorr);
}
double getFOV() {
return _pSlideBitmap->getFOV();
}
void setFOV(double fov) {
_pSlideBitmap->setFOV(fov);
}
CBofPalette *getPalette() {
return _pSlideBitmap->getPalette();
}
uint32 benchmark();
public:
static void flushInputEvents();
void onClose() override;
void onMouseMove(uint32 nFlags, CBofPoint *p, void * = nullptr) override;
void onLButtonDown(uint32 nFlags, CBofPoint *point, void * = nullptr) override;
void onLButtonUp(uint32 nFlags, CBofPoint *point, void * = nullptr) override;
void onKeyHit(uint32 lKey, uint32 lRepCount) override;
virtual void onSize(uint32 nType, int cx, int cy);
void OnWindowPosChanging(WindowPos *lpwndpos);
ErrorCode onCursorUpdate(int nCurrObj) override;
static CBagPDA *_pPDABmp; // Pointer to the PDA object
/**
* Deactivate the PDA by calling the PDA->deactivate() directly.
* This is called from the PDA ON/OFF button
*/
bool deactivatePDA();
/**
* Activate the PDA by calling the PDA->deactivate() directly.
* This is called on a mouse down anywhere on the deactivated PDA.
*/
bool activatePDA();
void waitForPDA();
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,246 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/parse_object.h"
#include "bagel/spacebar/boflib/app.h"
namespace Bagel {
namespace SpaceBar {
void CBagParseObject::initialize() {
}
CBagParseObject::CBagParseObject() {
_bAttached = false;
}
int CBagParseObject::getIntFromStream(CBagIfstream &istr, int &nNum) {
char ch;
char szLocalStr[256];
int i = 0;
while (Common::isDigit(ch = (char)istr.peek())) {
ch = (char)istr.getCh();
szLocalStr[i++] = ch;
assert(i < 256);
}
szLocalStr[i] = 0;
nNum = atoi(szLocalStr);
return ch;
}
int CBagParseObject::getStringFromStream(CBagIfstream &istr, CBofString &sStr, const CBofString &sEndChars, bool bPutBack) {
bool bDone = false;
char ch = 0;
sStr = "";
do {
if (istr.eof())
bDone = true;
else
ch = (char)istr.getCh();
for (int i = 0; !bDone && i < sEndChars.getLength(); ++i) {
if (sEndChars[i] == ch)
bDone = true;
}
if (!bDone)
sStr += ch;
} while (!bDone);
if (bPutBack)
istr.putBack();
return ch;
}
int CBagParseObject::getRectFromStream(CBagIfstream &istr, CBofRect &rect) {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString str(szLocalStr, 256);
// The first char must be a [
char ch = (char)istr.getCh();
if (ch != '[')
return -1;
// Get the left-coord
getStringFromStream(istr, str, ",");
rect.left = atoi(str);
// Get the top-coord
getStringFromStream(istr, str, "],", true);
rect.top = atoi(str);
// If ',' then get the size coords
ch = (char)istr.getCh();
if (ch == ',') {
// Get the right-coord (optional)
getStringFromStream(istr, str, ",");
rect.right = atoi(str);
// Get the bottom-coord (optional)
getStringFromStream(istr, str, "]");
rect.bottom = atoi(str);
} else {
rect.right = rect.left - 1;
rect.bottom = rect.top - 1;
}
return 0;
}
int CBagParseObject::getAlphaNumFromStream(CBagIfstream &istr, CBofString &sStr) {
bool bDone = false;
char ch = 0;
sStr = "";
istr.eatWhite();
do {
if (istr.eof())
bDone = true;
else
ch = (char)istr.getCh();
if (Common::isAlnum(ch) || ch == '_' || ch == '-' || ch == '\\' || ch == '/' || ch == '.' || ch == ':' || ch == '$' || ch == 39 || ch == '~') {
sStr += ch;
} else {
bDone = true;
}
} while (!bDone);
istr.putBack();
return ch;
}
int CBagParseObject::getOperStrFromStream(CBagIfstream &istr, CBofString &sStr) {
bool bDone = false;
char ch = 0;
sStr = "";
istr.eatWhite();
do {
if (istr.eof())
bDone = true;
else
ch = (char)istr.getCh();
if (Common::isPunct(ch))
sStr += ch;
else
bDone = true;
} while (!bDone);
istr.putBack();
return ch;
}
int CBagParseObject::getKeywordFromStream(CBagIfstream &istr, CBagParseObject::KEYWORDS &keyword) {
keyword = CBagParseObject::UNKNOWN;
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
int rc = getAlphaNumFromStream(istr, sStr);
if (!sStr.find("SDEV")) {
keyword = CBagParseObject::STORAGEDEV;
} else if (!sStr.find("START_WLD")) {
keyword = CBagParseObject::START_WLD;
} else if (!sStr.find("VAR")) {
keyword = CBagParseObject::VARIABLE;
} else if (!sStr.find("DISKAUDIO")) {
// Specify the audio that get's played when user is asked to insert another CD.
keyword = CBagParseObject::DISKAUDIO;
} else if (!sStr.find("SYSSCREEN")) {
keyword = CBagParseObject::SYSSCREEN;
} else if (!sStr.find("DISKID")) {
keyword = CBagParseObject::DISKID;
} else if (!sStr.find("SHAREDPAL")) {
keyword = CBagParseObject::SHAREDPAL; // Allow shared palette at front of script
} else if (!sStr.find("PDASTATE")) {
keyword = CBagParseObject::PDASTATE; // allow shared palette at front of script
} else if (!sStr.find("CURSOR")) {
keyword = CBagParseObject::CURSOR;
} else if (!sStr.find("WIELDCURSOR")) {
keyword = CBagParseObject::WIELDCURSOR;
} else if (!sStr.find("REM") || !sStr.find("//")) {
keyword = CBagParseObject::REMARK;
}
return rc;
}
int CBagParseObject::putbackStringOnStream(CBagIfstream &istr, const CBofString &sStr) {
int nLen = sStr.getLength();
while (nLen > 0) {
--nLen;
istr.putBack();
}
return 0;
}
int CBagParseObject::parseAlertBox(CBagIfstream &istr, const char *sTitle, const char *sFile, int nLine) {
char str[256];
CBofString s = sFile;
Common::String tmp = Common::String::format("(%d)@%d", nLine, istr.getLineNumber());
s += tmp.c_str();
s += ":";
s += istr.getLineString();
istr.getLine(str, 255);
s += str;
istr.getLine(str, 255);
s += str;
istr.getLine(str, 255);
s += str;
bofMessageBox(s, sTitle);
return 0;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,104 @@
/* 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 BAGEL_BAGLIB_PARSE_OBJECT_H
#define BAGEL_BAGLIB_PARSE_OBJECT_H
#include "bagel/spacebar/baglib/ifstream.h"
#include "bagel/boflib/error.h"
#include "bagel/boflib/rect.h"
#include "bagel/boflib/string.h"
namespace Bagel {
namespace SpaceBar {
#define RECT_START_DELIM '['
#define RECT_END_DELIM ']'
#define RECT_VAR_DELIM ','
#define SDEV_START_DELIM '{'
#define SDEV_END_DELIM '}'
#define OBJ_START_DELIM '='
#define OBJ_END_DELIM ';'
enum ParseCodes {
PARSING_DONE = 0, UPDATED_OBJECT, UNKNOWN_TOKEN
};
class CBagParseObject {
public:
enum KEYWORDS {
UNKNOWN = 0,
STORAGEDEV,
START_WLD,
VARIABLE,
REMARK,
DISKID,
CURSOR,
SHAREDPAL,
DISKAUDIO,
PDASTATE,
SYSSCREEN,
WIELDCURSOR
};
private:
bool _bAttached;
public:
CBagParseObject();
virtual ~CBagParseObject() {
}
static void initialize();
virtual ErrorCode attach() {
_bAttached = true;
return ERR_NONE;
}
virtual ErrorCode detach() {
_bAttached = false;
return ERR_NONE;
}
virtual bool isAttached() {
return _bAttached;
}
virtual ParseCodes setInfo(CBagIfstream &) {
return PARSING_DONE;
}
int getStringFromStream(CBagIfstream &istr, CBofString &sStr, const CBofString &sEndChars, bool bPutBack = false);
int getAlphaNumFromStream(CBagIfstream &istr, CBofString &sStr);
int getOperStrFromStream(CBagIfstream &istr, CBofString &sStr);
int getIntFromStream(CBagIfstream &istr, int &nNum);
int getRectFromStream(CBagIfstream &istr, CBofRect &rect);
int getKeywordFromStream(CBagIfstream &istr, KEYWORDS &keyword);
int putbackStringOnStream(CBagIfstream &istr, const CBofString &sStr);
int parseAlertBox(CBagIfstream &istr, const char *sTitle, const char *sFile, int nLine);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,569 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/pda.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/boflib/sound.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/button_object.h"
#include "bagel/spacebar/baglib/character_object.h"
#include "bagel/spacebar/baglib/time_object.h"
namespace Bagel {
namespace SpaceBar {
bool CBagPDA::_flashingFl;
bool CBagPDA::_soundsPausedFl;
CBofList<CBagMovieObject *> *CBagPDA::_movieList;
extern bool g_allowattachActiveObjectsFl;
static bool g_bAutoUpdate;
void CBagPDA::initialize() {
_flashingFl = false;
_soundsPausedFl = false;
_movieList = nullptr;
g_bAutoUpdate = false;
}
CBagPDA::CBagPDA(CBofWindow *pParent, const CBofRect &xRect, bool bActivated)
: CBagStorageDevBmp(pParent, xRect),
SBBasePda(pParent, xRect, bActivated) {
_xSDevType = SDEV_PDA;
_activeHeight = 0;
_deactiveHeight = 0;
}
void CBagPDA::addToMovieQueue(CBagMovieObject *pMObj) {
// Make sure we've got a list.
if (_movieList == nullptr) {
_movieList = new CBofList<CBagMovieObject *>;
}
// Handle simple case first, if it is marked for don't queue, then don't
// add it at all. This is done to insure that insignificant movies
// such as "have you noticed your message light has been blinking" do not
// get queued (and subsequently play when they are no longer appropriate).
if (pMObj->isDontQueue()) {
return;
}
assert(_movieList != nullptr);
// Go through the whole movie list, make sure there are no dup's of
// this movie.
int nCount = _movieList->getCount();
for (int i = 0; i < nCount; i++) {
CBagMovieObject *p = _movieList->getNodeItem(i);
if (p->getFileName().find(pMObj->getFileName()) == 0) {
return;
}
}
_movieList->addToTail(pMObj);
}
CBagPDA::~CBagPDA() {
assert(isValidObject(this));
// Does not own list item, so no need to delete individual nodes
delete _movieList;
_movieList = nullptr;
}
ErrorCode CBagPDA::loadFile(const CBofString &sFile) {
assert(isValidObject(this));
ErrorCode errorCode = CBagStorageDev::loadFile(sFile);
if (_mooWnd) {
removeObject(_mooWnd);
}
if (_invWnd) {
removeObject(_invWnd);
}
if (_mapWnd) {
removeObject(_mapWnd);
}
if (_logWnd) {
removeObject(_logWnd);
}
return errorCode;
}
ErrorCode CBagPDA::attach() {
CBagStorageDev *pSDev;
ErrorCode errorCode = CBagStorageDevBmp::attach();
// Get PDA state info
getPdaState();
// Calculate the position for the pda
CBofRect bmpRect = getBitmap()->getRect();
CBofWindow *pGameWin = CBagel::getBagApp()->getMasterWnd()->getCurrentGameWindow();
CBofRect GameRect = pGameWin->getRect();
// When the pda is active it should sit flush with the bottom of the screen
_activeHeight = GameRect.height() - bmpRect.height();
// When it is deactivated it should be the active height less the total movement distance
_deactiveHeight = GameRect.height() - (bmpRect.height() - (_moveDist * _numMoves));
// Should be allowed to not find one.
if (!_mooWnd) {
pSDev = g_SDevManager->getStorageDevice(MOO_WLD);
if (pSDev != nullptr) {
_mooWnd = (CBagStorageDevBmp *)pSDev;
_mooWnd->setAssociateWnd(getAssociateWnd());
_mooWnd->setTransparent(false);
_mooWnd->setVisible(false);
errorCode = _mooWnd->attach();
}
}
if (!_invWnd) {
pSDev = g_SDevManager->getStorageDevice(INV_WLD);
if (pSDev != nullptr) {
_invWnd = (CBagStorageDevBmp *)pSDev;
_invWnd->setAssociateWnd(getAssociateWnd());
_invWnd->setTransparent(false);
_invWnd->setVisible(false);
errorCode = _invWnd->attach();
} else {
bofMessageBox("No PDA INVENTORY found", __FILE__);
errorCode = ERR_UNKNOWN;
}
}
if (!_mapWnd) {
pSDev = g_SDevManager->getStorageDevice(MAP_WLD);
if (pSDev != nullptr) {
_mapWnd = (CBagStorageDevBmp *)pSDev;
_mapWnd->setAssociateWnd(getAssociateWnd());
_mapWnd->setTransparent(false);
_mapWnd->setVisible(false);
errorCode = _mapWnd->attach();
} else {
bofMessageBox("No PDA MAP found", __FILE__);
errorCode = ERR_UNKNOWN;
}
}
if (!_logWnd) {
pSDev = g_SDevManager->getStorageDevice(LOG_WLD);
if (pSDev != nullptr) {
_logWnd = (CBagStorageDevBmp *)pSDev;
_logWnd->setAssociateWnd(getAssociateWnd());
_logWnd->setTransparent(false);
_logWnd->setVisible(false);
errorCode = _logWnd->attach();
}
}
if (_pdaMode == PDA_INV_MODE) {
showInventory();
} else if (_pdaMode == PDA_MAP_MODE) {
showMap();
} else if (_pdaMode == PDA_LOG_MODE) {
showLog();
}
return errorCode;
}
void CBagPDA::setPosInWindow(int cx, int cy, int nDist) {
CBofBitmap *pBmp = getBitmap();
if (!pBmp)
return;
CBofRect bmpRect = pBmp->getRect();
_moveDist = nDist;
CBofPoint pt;
pt.x = (cx - bmpRect.width()) / 2;
if (_activated)
pt.y = cy - bmpRect.height();
else
pt.y = cy - bmpRect.height() + _moveDist * _numMoves;
setRect(CBofRect(pt.x, pt.y, pt.x + pBmp->width() - 1, pt.y + pBmp->height() - 1));
}
bool CBagPDA::hideCurDisplay() {
SBBasePda::hideCurDisplay();
return true;
}
bool CBagPDA::restoreCurDisplay() {
SBBasePda::restoreCurDisplay();
return true;
}
bool CBagPDA::hideInventory() {
SBBasePda::hideInventory();
return true;
}
bool CBagPDA::showInventory() {
SBBasePda::showInventory();
return true;
}
ErrorCode CBagPDA::update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect, int /* nMaskColor */) {
// Update the zoom button (it might need to blink).
handleZoomButton(false);
ErrorCode errorCode = ERR_NONE;
if (_hidePdaFl)
return errorCode;
CBofRect r;
CBofRect *pr = pSrcRect;
if (_activating) {
CBofPoint loc = getPosition();
_activating--;
if (_activated) {
if (loc.y > _activeHeight) {
loc.y -= _moveDist;
if (pSrcRect) {
r = *pSrcRect;
pSrcRect->bottom += _moveDist;
pr = &r;
}
}
} else if (loc.y < _deactiveHeight) {
loc.y += _moveDist;
if (pSrcRect) {
r = *pSrcRect;
pSrcRect->top -= _moveDist;
pr = &r;
}
}
setPosition(loc);
pt = loc;
}
// We have gotten back from a zoom and we need to straighten up
if (SBBasePda::_pdaMode == PDA_INV_MODE && _curDisplay != _invWnd) {
showInventory();
} else if (SBBasePda::_pdaMode == PDA_MAP_MODE && _curDisplay != _mapWnd) {
showMap();
} else if (SBBasePda::_pdaMode == PDA_LOG_MODE && _curDisplay != _logWnd) {
showLog();
}
bool bIsMovieWaiting = isMovieWaiting();
bool bMoviePlaying = false;
if ((!isActivated()) && // Must be down
((_pdaMode == PDA_MAP_MODE) ||
(bIsMovieWaiting && _pdaMode != PDA_MOO_MODE))) {
// Reset to reflect we know it happened
setPreFiltered(false);
// Play the movie if it is ready.
if (bIsMovieWaiting == true) {
runWaitingMovie();
}
} else if (_pdaMode == PDA_MOO_MODE) {
// If we're playing a pda movie, then make sure we continue to update.
bMoviePlaying = true;
}
// If the official decree from on high has been given to update, do so!
errorCode = CBagStorageDevBmp::update(pBmp, pt, pr, _nMaskColor);
// If the PDA is activating then redraw our black background
bool bWandAnimating = CBagCharacterObject::pdaWandAnimating();
if (isActivating() || bWandAnimating || bMoviePlaying) {
CBagStorageDevWnd *pMainWin = (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev());
((CBagPanWindow *)pMainWin)->setPreFilterPan(true);
} else if (!isActivated() && (SBBasePda::_pdaMode != PDA_MAP_MODE)) {
// If it is not activated, then don't bother redrawing it or the objects
// inside of it.
setDirty(false);
}
return errorCode;
}
bool CBagPDA::isInside(const CBofPoint &xPoint) {
CBofBitmap *pSrcBmp = getBitmap();
if (getRect().ptInRect(xPoint) && _nMaskColor >= 0) {
if (pSrcBmp) {
int x = xPoint.x - getRect().left;
int y = xPoint.y - getRect().top;
int c = pSrcBmp->readPixel(x, y);
return (c != _nMaskColor);
}
return true;
}
return false;
}
void CBagPDA::onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void *info) {
CBagStorageDevWnd *pMainWin = (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev());
if (!isActivated() && _pdaMode != PDA_INV_MODE) { // if the PDA is not active, activate it
if (isInside(*xPoint)) {
// Make sure the entire screen gets redrawn for an activate
((CBagPanWindow *)pMainWin)->setPreFilterPan(true);
activate();
setDirty(true);
attachActiveObjects(); // Forces PDA to be reevaluated.
}
return;
}
// Else, call the default func
CBofPoint RealPt = devPtToViewPort(*xPoint);
if (_curDisplay && _curDisplay->getRect().ptInRect(RealPt)) {
_curDisplay->onLButtonUp(nFlags, &RealPt, info);
} else {
// if not in the PDA view port then check and make sure it is activated.
if (SBBasePda::_pdaMode == PDA_INV_MODE && !isActivated()) {
if (isInside(*xPoint)) {
// Make sure the entire screen gets redrawn for an activate
((CBagPanWindow *)pMainWin)->setPreFilterPan(true);
activate();
setDirty(true);
}
return;
}
// If it's in one of the buttons, then pass it off to the
// sdev bmp code.
if (isActivated()) {
bool bButtonHit = false;
CBofList<CBagObject *> *pList = getObjectList();
int nCount = (pList == nullptr ? 0 : pList->getCount());
// Go through all the buttons and see if we hit any of them.
for (int i = 0; i < nCount; i++) {
CBagObject *pObj = pList->getNodeItem(i);
if (pObj->getType() == BUTTON_OBJ && pObj->getRect().ptInRect(RealPt)) {
bButtonHit = true;
break;
}
}
// Deactivate the PDA if we didn't hit a button.
if (bButtonHit || _pdaMode == PDA_NO_MODE) {
CBagStorageDevBmp::onLButtonUp(nFlags, xPoint, info);
} else {
((CBagPanWindow *)pMainWin)->setPreFilterPan(true);
deactivate();
}
}
}
// After a change of state, check if we should be flashing our
// zoom button or not.
handleZoomButton(false);
}
void CBagPDA::onLButtonDown(uint32 nFlags, CBofPoint *xPoint, void *info) {
// All we want to do here is if we had a mouse down on our
// zoom button, then make sure we have the real zoom button current (that
// is, if we have the inventory front and center).
handleZoomButton(true);
CBagStorageDevBmp::onLButtonDown(nFlags, xPoint, info);
}
CBagObject *CBagPDA::onNewButtonObject(const CBofString &) {
CBagButtonObject *PdaButtObj = new CBagButtonObject();
PdaButtObj->setCallBack(pdaButtonHandler, (SBBasePda *)this);
return PdaButtObj;
}
bool CBagPDA::paintFGObjects(CBofBitmap *pBmp) {
if (_curDisplay) {
// If we get here, then we are guaranteed that our pda
// needs updating, so dirty the whole list before updating...
// this assures that all objects will be updated (that are active).
makeListDirty(_curDisplay->getObjectList());
CBofRect tmp = getRect();
_curDisplay->update(pBmp, getPosition(), &tmp);
}
return true;
}
CBagObject *CBagPDA::onNewUserObject(const CBofString &sInit) {
CBagTimeObject *pTimeObj = nullptr;
if (sInit == "TIME") {
pTimeObj = new CBagTimeObject();
}
return pTimeObj;
}
void CBagPDA::handleZoomButton(bool bButtonDown) {
CBagButtonObject *pZoomRegular = nullptr;
CBagButtonObject *pZoomFlash = nullptr;
char szLocalBuff[256];
CBofString sDevice(szLocalBuff, 256);
sDevice = "BPDA_WLD";
CBagStorageDev *pPda = g_SDevManager->getStorageDevice(sDevice);
if (pPda) {
sDevice = PDA_ZOOMFLASH;
pZoomFlash = (CBagButtonObject *)pPda->getObject(sDevice);
pZoomRegular = (CBagButtonObject *)pPda->getObject(PDA_ZOOM);
}
// Only change the flashing state if we're not in a button down situation
if (pZoomFlash && pZoomRegular && pZoomRegular->getState() != 1) {
if (bButtonDown == false && _pdaMode == PDA_INV_MODE && (_pdaPos == PDA_UP) && _invWnd && _invWnd->getNumFloatPages() > 1) {
// Make the zoom button blink, to indicate more icons
if (_flashingFl == false) {
// Don't allow attachActiveObjects() to be called in here
g_allowattachActiveObjectsFl = false;
pPda->activateLocalObject(pZoomFlash);
pPda->deactivateLocalObject(pZoomRegular);
g_allowattachActiveObjectsFl = true;
pZoomFlash->setActive(true);
pZoomRegular->setActive(false);
pZoomFlash->setAnimated(true);
pZoomFlash->setAlwaysUpdate(true);
_flashingFl = true;
}
} else if (_flashingFl) {
// Don't allow attachActiveObjects() to be called in here
g_allowattachActiveObjectsFl = false;
pPda->deactivateLocalObject(pZoomFlash);
pPda->activateLocalObject(pZoomRegular);
g_allowattachActiveObjectsFl = true;
pZoomFlash->setActive(false);
pZoomRegular->setActive(true);
pZoomFlash->setAnimated(false);
pZoomFlash->setAlwaysUpdate(false);
_flashingFl = false;
}
}
}
void CBagPDA::removeFromMovieQueue(CBagMovieObject *pMObj) {
if (_movieList == nullptr)
return;
int nCount = _movieList->getCount();
for (int i = 0; i < nCount; i++) {
CBagMovieObject *p = _movieList->getNodeItem(i);
if (pMObj == p) {
_movieList->remove(i);
break;
}
}
}
bool CBagPDA::isMovieWaiting() {
bool bMovieWaiting = false;
if (_movieList) {
bMovieWaiting = (_movieList->getCount() > 0);
}
// If our sounds are paused, and our movie is done playing,
// then start up our sounds again.
if (_soundsPausedFl == true && isMoviePlaying() == false) {
CBofSound::resumeSounds();
_soundsPausedFl = false;
}
return bMovieWaiting;
}
void CBagPDA::runWaitingMovie() {
// Will only run a movie if it is ready to be run
if (!_movieList)
return;
int nCount = _movieList->getCount();
for (int i = 0; i < nCount; i++) {
CBagMovieObject *pMObj = _movieList->getNodeItem(i);
if (pMObj->asynchPDAMovieCanPlay()) {
_soundsPausedFl = true;
// pause all sounds
CBofSound::pauseSounds();
pMObj->runObject();
removeFromMovieQueue(pMObj);
}
}
}
ErrorCode CBagPDA::attachActiveObjects() {
static bool bAlready = false;
// If not already in this function
if (!bAlready) {
// Stop recursion
bAlready = true;
SBBasePda::attachActiveObjects();
CBagStorageDevBmp::attachActiveObjects();
bAlready = false;
}
return _errCode;
}
ErrorCode CBagPDA::detachActiveObjects() {
SBBasePda::detachActiveObjects();
return CBagStorageDevBmp::detachActiveObjects();
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,170 @@
/* 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 BAGEL_BAGLIB_PDA_H
#define BAGEL_BAGLIB_PDA_H
#include "bagel/spacebar/baglib/base_pda.h"
#include "bagel/spacebar/baglib/movie_object.h"
namespace Bagel {
namespace SpaceBar {
#define PDA_INCREMENT 13
class CBagPDA : public CBagStorageDevBmp, public SBBasePda {
protected:
int _activeHeight;
int _deactiveHeight;
static bool _flashingFl;
static bool _soundsPausedFl;
static CBofList<CBagMovieObject *> *_movieList;
public:
/**
* Constructor
* @param pParent Pointer to the parent window
* @param xRect Rect of the pda
* @param bActivated State of PDA whe constructed (optional)
*/
CBagPDA(CBofWindow *pParent = nullptr, const CBofRect &xRect = CBofRect(), bool bActivated = false);
/**
* Destructor
*/
virtual ~CBagPDA();
static void initialize();
ErrorCode attach() override;
/**
* Positions the PDA centered vertically and window
* @param cx x position
* @param cy y position
* @param nDist Distance to bring move PDA
*/
void setPosInWindow(int cx, int cy, int nDist = PDA_INCREMENT);
/**
* Update the PDA to the screen and then call CBagStorageDevBmp update
* @param pBmp Background bitmap to paint to
* @param pt Offset into bitmap
* @param pSrcRect Clip rect of the object to be painted
* @param nMaskColor Mask color for the object
*/
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect = nullptr, int nMaskColor = -1) override;
/**
* Called to overload specific types of sprite objects
* @param pBmp Bitmap
* @return Success/failure
*/
bool paintFGObjects(CBofBitmap *pBmp) override;
ErrorCode loadFile(const CBofString &sFile) override;
/**
* Called to overload specific types of sprite objects
* @param sInit Init
* @return Pointer to the new object
*/
CBagObject *onNewButtonObject(const CBofString &sInit) override;
/**
* Called on the mouse left button down
* Is the PDA is deactivated mouse down activates the PDA
* else it calls CBagStorageDevBmp::onLButtonDown
* @param nFlags Flags
* @param xPoint X, Y position
* @param info Optional info
*/
void onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void *info = nullptr) override;
/**
* Called on the mouse left button down
* @param nFlags Flags
* @param xPoint X, Y position
* @param info Optional info
*/
void onLButtonDown(uint32 nFlags, CBofPoint *xPoint, void *info = nullptr) override;
bool isInside(const CBofPoint &xPoint) override;
CBagObject *onNewUserObject(const CBofString &sInit) override;
/**
* Allow the movie code to queue up asynch pda messages
* Must be before the destructor
*/
static void addToMovieQueue(CBagMovieObject *);
/**
* Just remove this message from the queue, remember that we
* don't own this object, so just remove it, don't delete it!!!!
*/
static void removeFromMovieQueue(CBagMovieObject *);
/**
* Return true if a movie is waiting to play.
*/
static bool isMovieWaiting();
static bool isMoviePlaying() {
return _pdaMode == PDA_MOO_MODE;
}
static void runWaitingMovie();
/**
* SHow the inventory
*/
bool showInventory() override;
/**
* Hide the inventory
*/
bool hideInventory() override;
/**
* Hide the current display
*/
bool hideCurDisplay() override;
/**
* Restore display
*/
bool restoreCurDisplay() override;
ErrorCode attachActiveObjects() override;
ErrorCode detachActiveObjects() override;
/**
* Handle switching back and forth from our flashing zoom button
*/
void handleZoomButton(bool bButtonDown);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,74 @@
/* 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 BAGEL_BAGLIB_RES_H
#define BAGEL_BAGLIB_RES_H
namespace Bagel {
namespace SpaceBar {
// This section should not change, the first cursor is always invalid
#define BOF_INVALID 0
// OBJ
// Lists object types
#define BOF_BMP_OBJ 1
#define BOF_SPRITE_OBJ 2
#define BOF_BUTTON_OBJ 3
#define BOF_SOUND_OBJ 4
#define BOF_LINK_OBJ 5
#define BOF_TEXT_OBJ 6
#define BOF_CHAR_OBJ 7
#define BOF_VAR_OBJ 8
#define BOF_AREA_OBJ 9
#define BOF_MOVIE_OBJ 11
#define BOF_COMM_OBJ 12
#define BOF_EXPRESS_OBJ 13
#define BOF_THING_OBJ 14
#define BOF_RESPRNT_OBJ 15
#define BOF_DOSSIER_OBJ 16
// PAN
// These CANNOT change
#define BOF_LT_CURSOR 14
#define BOF_UP_CURSOR 15
#define BOF_RT_CURSOR 16
#define BOF_DN_CURSOR 17
#define BOF_TAKE_HAND 18
#define BOF_HAND 19
// WLD
#define INV_WLD "INV_WLD"
#define LOG_WLD "LOG_WLD"
#define LOGZ_WLD "LOGZ_WLD"
#define MAP_WLD "MAP_WLD"
#define MOO_WLD "MOO_WLD"
#define PDA_WLD "BPDA_WLD"
#define PDAZ_WLD "BPDAZ_WLD"
#define THUD_WLD "THUD_WLD"
#define WIELD_WLD "BWIELD_WLD"
} // namespace SpaceBar
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
/* 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 BAGEL_BAGLIB_RP_OBJECT_H
#define BAGEL_BAGLIB_RP_OBJECT_H
#include "bagel/spacebar/baglib/dossier_object.h"
#include "bagel/spacebar/baglib/expression.h"
#include "bagel/spacebar/baglib/movie_object.h"
#include "bagel/spacebar/baglib/text_object.h"
namespace Bagel {
namespace SpaceBar {
class DossierObj {
public:
DossierObj();
virtual ~DossierObj();
CBagDossierObject *_pDossier;
CBofString _sDossier;
CBagExpression *_xDosExp;
bool _bDisplayDossier;
};
enum RPStates {
RP_NO_MODE = 0,
RP_RESULTS,
RP_READ_DOSSIER,
RP_REVIEW,
RP_MAIN_MENU
};
class CBagRPObject : public CBagObject {
private:
CBofList<DossierObj *> *_pTouchedList; // dossiers to show if alias touched it
CBofList<DossierObj *> *_pUntouchedList; // dossiers to show if alias did not touch it
CBagMovieObject *_pMovieObj; // a movie to play
CBofString _sMovieObj; // Name of movie
CBagVar *_pVarObj; // associated global var
CBagTextObject *_pDescObj; // description of residue printed object
CBagTextObject *_pObjectName; // description of residue printed object
CBofString _sObjectName; // description of residue printed object
CBagVar *_pSaveVar; // Var to save info to
CBagVar *_pTouchedVar; // variable indicating touched or not
int _nRPTime; // time to execute
CBofRect _cOrigRect; // Original text rect
int16 _nCurDossier; // index of current dossier
// member data boolS
bool _bOrigRectInit : true; // Original text initialized
bool _bRPReported : true; // been reported yet?
bool _bResPrinted : true; // been submitted?
bool _bTouched : true; // been touched?
bool _bRPRead : true; // been read
bool _bRPTimeSet : true; // had time residue printing occurred?
bool _bCurVisible : true; // Current one being displayed?
bool _bInitialized : true; // initialization state
bool _bMoviePlayed : true; // Has the movie played yet?
static CBofList<CBagRPObject *> *_pRPList; // all the residue print objects
static int32 _nLastRPQCheck; // last time we surfed the queue.
static CBagVar *_turnCount; // Ptr to turnCount global
static CBagVar *_pLogStateVar; // Ptr to log state global
static CBagVar *_pPrevLogStateVar; // Ptr to prev log state global
static CBagVar *_pBarLogPages; // Ptr to total pages global
static CBagVar *_pPrevBarPage; //
static CBagVar *_pCurBarPage; // current bar page
static CBagRPObject *_pCurRPObject; // Most recent residue print object.
static CBagRPObject *_pActivateThisGuy; // The one we want to activate
static RPStates _eRPMode; // Current state of display
public:
CBagRPObject();
virtual ~CBagRPObject();
ParseCodes setInfo(CBagIfstream &istr) override;
ErrorCode attach() override;
ErrorCode detach() override;
bool runObject() override;
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect, int) override;
void onLButtonUp(uint32, CBofPoint *, void * = nullptr) override;
void setTouchedDos(CBofString &s, CBagExpression *x);
void setUntouchedDos(CBofString &s, CBagExpression *x);
bool activateRPObject();
void deactivateRPObject();
bool getTimeSet() {
return _bRPTimeSet;
}
void setTimeSet(bool b) {
_bRPTimeSet = b;
}
void evaluateDossiers();
void saveResiduePrintedVars();
void restoreResiduePrintedVars();
bool initialize();
CBagDossierObject *getActiveDossier();
void setActiveDossier(CBagDossierObject *);
static bool addToMsgQueue(CBagRPObject *);
static bool zoomed();
// Command (bagcoobj) objects, activated from script
static int runResiduePrintedQueue();
static int updateResiduePrintedQueue();
static void deactivateResiduePrintedQueue();
static void activateResiduePrintedReview();
static void deactivateResiduePrintedReview();
static void setLogState(RPStates eLogMode);
static RPStates getLogState();
static void setLogPages(int);
static void showResiduePrintedReview();
static void hideResiduePrintedReview();
static int residuePrintedResultsWaiting();
static void removeAllFromMsgQueue(CBagRPObject *pRPObj);
static void showPdaLog();
static void synchronizeResiduePrintedObjects(bool);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,317 @@
/* 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/>.
*
*/
#include "common/algorithm.h"
#include "common/memstream.h"
#include "common/serializer.h"
#include "bagel/spacebar/baglib/save_game_file.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/misc.h"
#include "bagel/bagel.h"
namespace Bagel {
namespace SpaceBar {
#define WORLD_DIR "$SBARDIR\\WLD\\%s"
void StSavegameHeader::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_szTitle, MAX_SAVE_TITLE);
s.syncBytes((byte *)_szUserName, MAX_USER_NAME);
s.syncAsUint32LE(_bUsed);
}
void StVar::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_szName, MAX_VAR_NAME);
s.syncBytes((byte *)_szValue, MAX_VAR_VALUE);
s.syncAsUint16LE(_nType);
s.syncAsByte(_bGlobal);
s.syncAsByte(_bConstant);
s.syncAsByte(_bReference);
s.syncAsByte(_bTimer);
s.syncAsByte(_bRandom);
s.syncAsByte(_bNumeric);
s.syncAsByte(_bAttached);
s.syncAsByte(_bUsed);
}
void StVar::clear() {
Common::fill(_szName, _szName + MAX_VAR_NAME, '\0');
Common::fill(_szValue, _szValue + MAX_VAR_VALUE, '\0');
_nType = 0;
_bGlobal = 0;
_bConstant = 0;
_bReference = 0;
_bTimer = 0;
_bRandom = 0;
_bNumeric = 0;
_bAttached = 0;
_bUsed = 0;
}
void StObj::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_szName, MAX_OBJ_NAME);
s.syncBytes((byte *)_szSDev, MAX_SDEV_NAME);
s.syncAsUint32LE(_lState);
s.syncAsUint32LE(_lProperties);
s.syncAsUint32LE(_lType);
s.syncAsUint32LE(_lLoop);
s.syncAsUint32LE(_lSpeed);
s.syncAsByte(_bAttached);
s.syncAsByte(_bUsed);
s.syncAsUint16LE(_nFlags);
}
void StObj::clear() {
Common::fill(_szName, _szName + MAX_OBJ_NAME, '\0');
Common::fill(_szSDev, _szSDev + MAX_SDEV_NAME, '\0');
_lState = 0;
_lProperties = 0;
_lType = 0;
_lLoop = 0;
_lSpeed = 0;
_bAttached = 0;
_bUsed = 0;
_nFlags = 0;
}
void StBagelSave::synchronize(Common::Serializer &s) {
for (int i = 0; i < MAX_VARS; ++i)
_stVarList[i].synchronize(s);
for (int i = 0; i < MAX_OBJS; ++i)
_stObjList[i].synchronize(s);
for (int i = 0; i < MAX_OBJS; ++i)
_stObjListEx[i].synchronize(s);
s.syncBytes((byte *)_szScript, MAX_FNAME);
s.syncAsUint32LE(_nLocType);
for (int i = 0; i < MAX_CLOSEUP_DEPTH; ++i)
s.syncBytes((byte *)_szLocStack[i], MAX_SDEV_NAME);
s.syncAsUint16LE(_nLocX);
s.syncAsUint16LE(_nLocY);
s.syncAsUint16LE(_bUseEx);
s.syncAsUint16LE(_nFiller);
}
void StBagelSave::clear() {
for (int i = 0; i < MAX_VARS; ++i)
_stVarList[i].clear();
for (int i = 0; i < MAX_OBJS; ++i) {
_stObjList[i].clear();
_stObjListEx[i].clear();
}
Common::fill(_szScript, _szScript + MAX_FNAME, '\0');
_nLocType = 0;
for (int i = 0; i < MAX_CLOSEUP_DEPTH; ++i)
Common::fill(_szLocStack[i], _szLocStack[i] + MAX_SDEV_NAME, '\0');
_nLocX = 0;
_nLocY = 0;
_bUseEx = 0;
_nFiller = 0;
}
CBagSaveGameFile::CBagSaveGameFile(bool isSaving) {
setFile("spacebar.sav",
isSaving ?
(CDF_MEMORY | CDF_ENCRYPT | CDF_KEEPOPEN | CDF_CREATE | CDF_SAVEFILE) :
(CDF_MEMORY | CDF_ENCRYPT | CDF_KEEPOPEN | CDF_SAVEFILE)
);
}
ErrorCode CBagSaveGameFile::writeSavedGame() {
assert(isValidObject(this));
// Populate the save data
StBagelSave *saveData = new StBagelSave();
g_engine->_masterWin->fillSaveBuffer(saveData);
Common::String str = "./" + Common::String(saveData->_szScript);
str.replace('/', '\\');
Common::strcpy_s(saveData->_szScript, str.c_str());
// Set up header fields
StSavegameHeader header;
Common::strcpy_s(header._szTitle, "ScummVM Save");
Common::strcpy_s(header._szUserName, "ScummVM User");
header._bUsed = 1;
// Create the data buffer
Common::MemoryWriteStreamDynamic stream(DisposeAfterUse::YES);
Common::Serializer s(nullptr, &stream);
header.synchronize(s);
stream.writeUint32LE(StBagelSave::size());
saveData->synchronize(s);
// Add the record
addRecord(stream.getData(), stream.size(), true, 0);
delete saveData;
return _errCode;
}
ErrorCode CBagSaveGameFile::readSavedGame(int32 slotNum) {
assert(isValidObject(this));
int32 lRecNum = findRecord(slotNum);
if (lRecNum != -1) {
int32 lSize = getRecSize(lRecNum);
if (lSize == StSavegameHeader::size()) {
_errCode = ERR_FREAD;
} else {
byte *pBuf = (byte *)bofAlloc(lSize);
readRecord(lRecNum, pBuf);
// Load in the savegame
Common::MemoryReadStream stream(pBuf, lSize);
Common::Serializer s(&stream, nullptr);
StSavegameHeader header;
header.synchronize(s);
s.skip(4); // Skip save data structure size
StBagelSave *saveData = new StBagelSave();
saveData->synchronize(s);
bofFree(pBuf);
CBofString str(saveData->_szScript);
fixPathName(str);
const char *path = str.getBuffer();
assert(!strncmp(path, "./", 2));
Common::strcpy_s(saveData->_szScript, path + 2);
// Restore the game
g_engine->_masterWin->doRestore(saveData);
delete saveData;
}
} else {
_errCode = ERR_FREAD;
}
return _errCode;
}
ErrorCode CBagSaveGameFile::readTitle(int32 lSlot, StSavegameHeader *pSavedGame) {
assert(isValidObject(this));
// validate input
assert(lSlot >= 0 && lSlot < MAX_SAVED_GAMES);
assert(pSavedGame != nullptr);
int32 lRecNum = findRecord(lSlot);
if (lRecNum != -1) {
int32 lSize = getRecSize(lRecNum);
byte *pBuf = (byte *)bofAlloc(lSize);
readRecord(lRecNum, pBuf);
// Fill StSavegameHeader structure with this game's saved info
memcpy(pSavedGame, pBuf, sizeof(StSavegameHeader));
bofFree(pBuf);
} else {
reportError(ERR_UNKNOWN, "Unable to find saved game #%ld in %s", lSlot, _szFileName);
}
return (_errCode);
}
ErrorCode CBagSaveGameFile::readTitleOnly(int32 lSlot, char *pGameTitle) {
assert(isValidObject(this));
// Validate input
assert(lSlot >= 0 && lSlot < MAX_SAVED_GAMES);
assert(pGameTitle != nullptr);
byte pBuf[MAX_SAVE_TITLE + 1];
int32 lRecNum = findRecord(lSlot);
if (lRecNum != -1) {
int32 lSize = MAX_SAVE_TITLE;
readFromFile(lRecNum, pBuf, lSize);
// Fill with current game title
memcpy(pGameTitle, pBuf, lSize);
} else {
reportError(ERR_UNKNOWN, "Unable to find saved game #%ld in %s", lSlot, _szFileName);
}
return _errCode;
}
int32 CBagSaveGameFile::getActualNumSaves() {
assert(isValidObject(this));
int32 lNumSaves = 0;
int32 lNumRecs = getNumSavedGames();
for (int32 i = 0; i < lNumRecs; i++) {
StSavegameHeader stGameInfo;
if (readTitle(i, &stGameInfo) == ERR_NONE) {
if (stGameInfo._bUsed) {
lNumSaves++;
}
} else {
break;
}
}
return (lNumSaves);
}
bool CBagSaveGameFile::anySavedGames() {
assert(isValidObject(this));
int32 lNumRecs = getNumSavedGames();
for (int32 i = 0; i < lNumRecs; i++) {
StSavegameHeader stGameInfo;
if (readTitle(i, &stGameInfo) == ERR_NONE) {
if (stGameInfo._bUsed) {
return true;
}
} else {
break;
}
}
return false;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,159 @@
/* 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 BAGEL_BAGLIB_SAVE_GAME_FILE_H
#define BAGEL_BAGLIB_SAVE_GAME_FILE_H
#include "common/serializer.h"
#include "bagel/spacebar/boflib/dat_file.h"
namespace Bagel {
namespace SpaceBar {
#define MAX_SAVED_GAMES 40
#define MAX_SAVE_TITLE 128
#define MAX_USER_NAME 64
struct StSavegameHeader {
char _szTitle[MAX_SAVE_TITLE] = { '\0' };
char _szUserName[MAX_USER_NAME] = { '\0' };
uint32 _bUsed = 0;
void synchronize(Common::Serializer &s);
static int size() {
return MAX_SAVE_TITLE + MAX_USER_NAME + 4;
}
};
#define MAX_SDEV_NAME 40
#define MAX_CLOSEUP_DEPTH 4
#define MAX_VARS 1000
#define MAX_VAR_NAME 40
#define MAX_VAR_VALUE 60
struct StVar {
char _szName[MAX_VAR_NAME];
char _szValue[MAX_VAR_VALUE];
uint16 _nType;
byte _bGlobal;
byte _bConstant;
byte _bReference;
byte _bTimer;
byte _bRandom;
byte _bNumeric;
byte _bAttached;
byte _bUsed; // If this entry is used or not
void synchronize(Common::Serializer &s);
void clear();
};
#define MAX_OBJ_NAME 40
#define MAX_SDEV_NAME 40
#define MAX_OBJS 1000
struct StObj {
char _szName[MAX_OBJ_NAME];
char _szSDev[MAX_SDEV_NAME];
uint32 _lState;
uint32 _lProperties;
uint32 _lType;
uint32 _lLoop;
uint32 _lSpeed;
byte _bAttached;
byte _bUsed;
uint16 _nFlags; // Flags for kicks...
void synchronize(Common::Serializer &s);
void clear();
};
// Flags for the st_obj structure
#define mIsMsgWaiting 0x0001
/**
* Savegame data structure
*/
struct StBagelSave {
StVar _stVarList[MAX_VARS];
StObj _stObjList[MAX_OBJS];
StObj _stObjListEx[MAX_OBJS];
char _szScript[MAX_FNAME]; // Name of current world file (no path)
uint32 _nLocType; // TYPE_PAN, TYPE_CLOSEUP, etc...
char _szLocStack[MAX_CLOSEUP_DEPTH][MAX_SDEV_NAME]; // Your storage device stack
uint16 _nLocX; // X Location in PAN
uint16 _nLocY; // Y Location in PAN
uint16 _bUseEx;
uint16 _nFiller; // Make structs align
void synchronize(Common::Serializer &s);
void clear();
static int size() {
return 318432;
}
};
/**
* Handles reading/writing the original savegame file that contains
* all the saves. Used by the console save/load commands.
*/
class CBagSaveGameFile : public CBofDataFile {
public:
CBagSaveGameFile(bool isSaving);
int32 getNumSavedGames() const {
return getNumberOfRecs();
}
int32 getActualNumSaves();
bool anySavedGames();
/**
* Saves a BAGEL game to current save game file
*/
ErrorCode writeSavedGame();
/**
* Restore a BAGEL saved game
*/
ErrorCode readSavedGame(int32 slotNum);
/**
* Reads a BAGEL saved game title
*/
ErrorCode readTitle(int32 lSlot, StSavegameHeader *pSavedGame);
ErrorCode readTitleOnly(int32 lSlot, char *pGameTitle);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,422 @@
/* 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/>.
*
*/
#include "common/file.h"
#include "bagel/boflib/event_loop.h"
#include "bagel/spacebar/baglib/sound_object.h"
#include "bagel/bagel.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/log.h"
namespace Bagel {
namespace SpaceBar {
// There is only one allowed at a time
CBofSound *CBagSoundObject::_pMidiSound;
void CBagSoundObject::initialize() {
_pMidiSound = nullptr;
}
CBagSoundObject::CBagSoundObject() {
_xObjType = SOUND_OBJ;
_pSound = nullptr;
// Assume MIX if not specified
_wFlags = SOUND_MIX;
_nVol = VOLUME_INDEX_DEFAULT;
CBagObject::setState(0);
_bWait = false;
_nLoops = 1;
setVisible(false);
CBagObject::setOverCursor(3);
}
CBagSoundObject::~CBagSoundObject() {
CBagSoundObject::detach();
}
ErrorCode CBagSoundObject::attach(CBofWindow *pWnd) {
newSound(pWnd);
return CBagObject::attach();
}
void CBagSoundObject::newSound(CBofWindow *pWin) {
killSound();
_pSound = new CBofSound(pWin, getFileName(), _wFlags, _nLoops);
_pSound->setVolume(_nVol);
_pSound->setQSlot(getState());
}
void CBagSoundObject::killSound() {
delete _pSound;
_pSound = nullptr;
}
ErrorCode CBagSoundObject::detach() {
killSound();
return CBagObject::detach();
}
bool CBagSoundObject::runObject() {
if (((_wFlags & SOUND_MIDI) && CBagMasterWin::getMidi()) || (((_wFlags & SOUND_WAVE) || (_wFlags & SOUND_MIX)) && CBagMasterWin::getDigitalAudio())) {
if (_pSound && _pMidiSound != _pSound) {
_pSound->setQSlot(getState());
_pSound->play();
// If waiting until this sound finishes
if (_bWait) {
// Show busy cursor
CBagMasterWin::setActiveCursor(6);
EventLoop limiter(EventLoop::FORCE_REPAINT);
while (_pSound->isPlaying()) {
CBofSound::audioTask();
if (limiter.frame()) {
_pSound->stop();
break;
}
}
}
if (_wFlags & SOUND_MIDI)
_pMidiSound = _pSound;
} else if (!(_wFlags & SOUND_MIDI)) {
/* if no sound */
int nExt = getFileName().getLength() - 4; // ".EXT"
if (nExt <= 0) {
logError("Sound does not have a file name or proper extension. Please write better scripts.");
return false;
}
CBofString sBaseStr = getFileName().left(nExt) + ".TXT";
Common::File f;
if (fileExists(sBaseStr) && f.open(sBaseStr.getBuffer())) {
Common::String line = f.readLine();
bofMessageBox(line.c_str(), "Using .TXT for missing .WAV!");
f.close();
return true;
}
logError(buildString("Sound TEXT file could not be read: %s. Why? because we like you ...", getFileName().getBuffer()));
return false;
}
}
return CBagObject::runObject();
}
ParseCodes CBagSoundObject::setInfo(CBagIfstream &istr) {
bool nObjectUpdated = false;
while (!istr.eof()) {
istr.eatWhite(); // Eat any white space between script elements
char ch = (char)istr.peek();
switch (ch) {
// VOLUME
//
case 'V': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("VOLUME")) {
istr.eatWhite();
int n;
getIntFromStream(istr, n);
setVolume(n);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// AS [WAVE|MIDI] - how to run the link
//
case 'A': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256); // performance improvement
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("AS")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("WAVE")) {
setWave();
nObjectUpdated = true;
} else if (!sStr.find("MIDI")) {
setMidi();
nObjectUpdated = true;
} else if (!sStr.find("SYNC")) {
setSync();
nObjectUpdated = true;
} else if (!sStr.find("ASYNC")) {
setASync();
nObjectUpdated = true;
// Mix and Wait
//
} else if (!sStr.find("WAITMIX")) {
setMix();
_bWait = true;
nObjectUpdated = true;
// Queue and Wait
//
} else if (!sStr.find("WAITQUEUE")) {
setQueue();
_bWait = true;
nObjectUpdated = true;
} else if (!sStr.find("QUEUE")) {
setQueue();
nObjectUpdated = true;
} else if (!sStr.find("MIX")) {
setMix();
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
putbackStringOnStream(istr, "AS ");
}
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
// LOOP PROPERTY FOR SOUNDS
case 'L': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256); // performance improvement
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("LOOP")) {
istr.eatWhite();
getIntFromStream(istr, _nLoops);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
// Oversound attribute for sound object
case 'S': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256); // performance improvement
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("SOUNDOVEROK")) {
setSoundOver();
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
//
// No match return from function
//
default: {
ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
nObjectUpdated = true;
} else { // rc==UNKNOWN_TOKEN
if (nObjectUpdated)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
}
break;
} // end switch
} // end while
return PARSING_DONE;
}
void CBagSoundObject::setQueue(bool b) {
if (b) {
_wFlags = SOUND_MIX | SOUND_QUEUE;
} else {
_wFlags &= ~SOUND_QUEUE;
}
}
int CBagSoundObject::getVolume() {
return _nVol;
}
void CBagSoundObject::setVolume(int nVol) {
_nVol = (byte)nVol;
if (isAttached()) {
if (_pSound != nullptr) {
_pSound->setVolume(_nVol);
}
}
}
bool CBagSoundObject::isPlaying() {
bool bPlaying = false;
if (_pSound != nullptr) {
bPlaying = _pSound->playing();
}
return bPlaying;
}
bool CBagSoundObject::isQueued() {
bool bQueued = false;
if (_pSound != nullptr) {
bQueued = _pSound->isQueued();
}
return bQueued;
}
void CBagSoundObject::setPlaying(bool bVal) {
if (((_wFlags & SOUND_MIDI) && CBagMasterWin::getMidi()) || (((_wFlags & SOUND_WAVE) || (_wFlags & SOUND_MIX)) && CBagMasterWin::getDigitalAudio())) {
if (bVal) {
if (_pSound && _pMidiSound != _pSound) {
_pSound->setQSlot(getState());
_pSound->play();
// If we are supposed to wait until this audio finishes
if (_bWait) {
// Show busy cursor
CBagMasterWin::setActiveCursor(6);
EventLoop limiter(EventLoop::FORCE_REPAINT);
while (_pSound->isPlaying()) {
CBofSound::audioTask();
if (limiter.frame()) {
_pSound->stop();
break;
}
}
}
if (_wFlags & SOUND_MIDI)
_pMidiSound = _pSound;
}
} else if (_pSound) {
_pSound->stop();
if (_wFlags & SOUND_MIDI)
_pMidiSound = nullptr;
}
}
}
void CBagSoundObject::setNumOfLoops(int n) {
_nLoops = n; // Only have ability to set at creation of BofSound
}
int CBagSoundObject::getProperty(const CBofString &sProp) {
if (!sProp.find("VOLUME")) {
return getVolume();
}
if (!sProp.find("QUEUED")) {
return isQueued();
}
if (!sProp.find("PLAYING")) {
return isPlaying();
}
if (!sProp.find("LOOP")) {
return _nLoops;
}
return CBagObject::getProperty(sProp);
}
void CBagSoundObject::setProperty(const CBofString &sProp, int nVal) {
if (!sProp.find("VOLUME")) {
setVolume(nVal);
} else if (!sProp.find("PLAYING")) {
if (nVal == 1)
setPlaying();
else
setPlaying(false);
} else if (!sProp.find("LOOP")) {
setNumOfLoops(nVal);
} else {
CBagObject::setProperty(sProp, nVal);
}
}
void CBagSoundObject::setSync(bool b) {
_wFlags = SOUND_WAVE;
if (!b)
_wFlags |= SOUND_ASYNCH;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,125 @@
/* 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 BAGEL_BAGLIB_SOUND_OBJECT_H
#define BAGEL_BAGLIB_SOUND_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/boflib/sound.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagSoundObject is an object that can be place within the slide window.
*/
class CBagSoundObject : public CBagObject {
private:
static CBofSound *_pMidiSound; // There is only one allowed at a time
CBofSound *_pSound;
uint16 _wFlags;
int _nLoops;
byte _nVol;
protected:
byte _bWait;
public:
CBagSoundObject();
virtual ~CBagSoundObject();
static void initialize();
void killSound();
void newSound(CBofWindow *pWin);
// Return true if the Object had members that are properly initialized/de-initialized
ErrorCode attach() override {
return attach((CBofWindow *)CBagel::getBagApp()->getMasterWnd());
}
ErrorCode attach(CBofWindow *pWnd);
bool isAttached() override {
return _pSound != nullptr;
}
ErrorCode detach() override;
CBofSound *getLastMidi() {
return _pMidiSound;
}
CBofSound *getSound() {
return _pSound;
}
void setWave() {
_wFlags = SOUND_WAVE;
}
void setMidi() {
_wFlags = (SOUND_MIDI | SOUND_LOOP);
}
// Gives ability to sound over certain sounds
void setSoundOver() {
_wFlags |= SOUND_OVEROK;
}
void setSync(bool b = true);
void setASync(bool b = true) {
setSync(!b);
}
bool isSync() {
return _wFlags & SOUND_ASYNCH;
}
void setMix() {
_wFlags = SOUND_MIX;
}
void setQueue(bool b = true);
bool runObject() override;
void setVolume(int nVol);
int getVolume();
void setNumOfLoops(int n);
int getProperty(const CBofString &sProp) override;
void setProperty(const CBofString &sProp, int nVal) override;
/**
* Takes in info and then removes the relative information and returns
* the info without the relevant info.
*/
ParseCodes setInfo(CBagIfstream &istr) override;
// Added properties to sound object
bool isPlaying();
bool isQueued();
void setPlaying(bool bVal = true);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,281 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/sprite_object.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
namespace Bagel {
namespace SpaceBar {
CBagSpriteObject::CBagSpriteObject() : CBagObject() {
_xObjType = SPRITE_OBJ;
_xSprite = nullptr;
_nCels = 1;
_nWieldCursor = -1;
// Transparent by default
setTransparent();
CBagObject::setOverCursor(1);
setAnimated();
setTimeless(true);
// implement sprite framerates
setFrameRate(0);
_nLastUpdate = 0;
}
CBagSpriteObject::~CBagSpriteObject() {
CBagSpriteObject::detach();
}
ErrorCode CBagSpriteObject::attach() {
// If it's not already attached
if (!isAttached()) {
// Could not already have a sprite
assert(_xSprite == nullptr);
_xSprite = new CBofSprite();
if (_xSprite->loadSprite(getFileName(), getCels()) != false && (_xSprite->width() != 0) && (_xSprite->height() != 0)) {
if (isTransparent()) {
int nMaskColor = CBagel::getBagApp()->getChromaColor();
_xSprite->setMaskColor(nMaskColor);
}
// Set animated of the sprite to be the same as it's parent
_xSprite->setAnimated(isAnimated());
CBofPoint p = CBagObject::getPosition();
if (p.x == -1 && p.y == -1) // Fixed to allow for [0,0] positioning
setFloating();
else
_xSprite->setPosition(p.x, p.y);
setProperty("CURR_CEL", getState());
// This might add something to the PDA, make sure it gets redrawn.
CBagStorageDevWnd *pMainWin = (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev());
if (pMainWin != nullptr) {
pMainWin->setPreFilterPan(true);
}
} else {
reportError(ERR_FOPEN, "Could Not Open Sprite: %s", _xSprite->getFileName());
}
}
return CBagObject::attach();
}
ErrorCode CBagSpriteObject::detach() {
delete _xSprite;
_xSprite = nullptr;
return CBagObject::detach();
}
void CBagSpriteObject::setCels(int nCels) {
_nCels = nCels;
if (_xSprite)
_xSprite->setupCels(nCels);
}
void CBagSpriteObject::setPosition(const CBofPoint &pos) {
CBagObject::setPosition(pos);
if (_xSprite)
_xSprite->setPosition(pos.x, pos.y);
}
CBofRect CBagSpriteObject::getRect() {
CBofPoint p = getPosition();
CBofSize s;
if (_xSprite)
s = _xSprite->getSize();
return CBofRect(p, s);
}
//
// Takes in info and then removes the relative information and returns the info
// without the relevant info.
ParseCodes CBagSpriteObject::setInfo(CBagIfstream &istr) {
bool nObjectUpdated = false;
while (!istr.eof()) {
istr.eatWhite(); // not sure why this WAS NOT here.
char ch = (char)istr.peek();
switch (ch) {
//
// +n - n number of slides in sprite
//
case '+': {
int cels;
istr.getCh();
getIntFromStream(istr, cels);
setCels(cels);
nObjectUpdated = true;
}
break;
case '#': {
int curs;
istr.getCh();
getIntFromStream(istr, curs);
setWieldCursor(curs);
nObjectUpdated = true;
}
break;
case 'N': {
// NOANIM
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256); // performance improvement
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("NOANIM")) {
istr.eatWhite();
setAnimated(false);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
// handle a maximum framerate...
case 'F': {
// NOANIM
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("FRAMERATE")) {
int nFrameRate;
istr.eatWhite();
getIntFromStream(istr, nFrameRate);
// The frame rate is expressed in frames/second, so do some division
// here to store the number of milliseconds.
setFrameRate(1000 / nFrameRate);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
//
// no match return from function
//
default: {
ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
nObjectUpdated = true;
} else { // rc==UNKNOWN_TOKEN
if (nObjectUpdated)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
}
break;
}
}
return PARSING_DONE;
}
ErrorCode CBagSpriteObject::update(CBofBitmap *pBmp, CBofPoint pt, CBofRect * /*pSrcRect*/, int) {
if (_xSprite) {
int nFrameInterval = getFrameRate();
if (nFrameInterval != 0) {
uint32 nCurTime = getTimer();
if (nCurTime > _nLastUpdate + nFrameInterval) {
_xSprite->setBlockAdvance(false);
_nLastUpdate = nCurTime;
} else {
_xSprite->setBlockAdvance(true);
}
}
bool bPaintResult = _xSprite->paintSprite(pBmp, pt.x, pt.y);
// Don't have to redraw this item...
// setDirty (false);
if (!bPaintResult)
return ERR_UNKNOWN;
}
return ERR_NONE;
}
bool CBagSpriteObject::isInside(const CBofPoint &xPoint) {
if (_xSprite && getRect().ptInRect(xPoint)) {
if (isTransparent()) {
int x = xPoint.x - getRect().left;
int y = xPoint.y - getRect().top;
int c = _xSprite->readPixel(x, y);
int d = _xSprite->getMaskColor();
return (c != d);
}
return true;
}
return false;
}
void CBagSpriteObject::setProperty(const CBofString &sProp, int nVal) {
if (!sProp.find("STATE") || !sProp.find("CURR_CEL")) {
setState(nVal);
if (_xSprite)
_xSprite->setCel(nVal);
} else
CBagObject::setProperty(sProp, nVal);
}
int CBagSpriteObject::getProperty(const CBofString &sProp) {
if (!sProp.find("CURR_CEL")) {
if (_xSprite) {
return _xSprite->getCelIndex();
}
return 0;
}
return CBagObject::getProperty(sProp);
}
void CBagSpriteObject::setAnimated(bool b) {
_bAnimated = b;
if (_xSprite)
_xSprite->setAnimated(b);
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,97 @@
/* 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 BAGEL_BAGLIB_SPRITE_OBJECT_H
#define BAGEL_BAGLIB_SPRITE_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/boflib/gfx/sprite.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagSpriteObject is an object that can be place within the slide window.
*/
class CBagSpriteObject : public CBagObject {
private:
CBofSprite *_xSprite;
int _nCels;
int _nWieldCursor; // Ref Id for the objects over cursor
bool _bAnimated : 1;
int _nMaxFrameRate;
public:
CBagSpriteObject();
virtual ~CBagSpriteObject();
ErrorCode attach() override;
ErrorCode detach() override;
bool isAttached() override {
return _xSprite != nullptr;
}
ParseCodes setInfo(CBagIfstream &istr) override;
bool isInside(const CBofPoint &xPoint) override;
int getWieldCursor() const {
return _nWieldCursor;
}
void setWieldCursor(int n) {
_nWieldCursor = n;
}
CBofSprite *getSprite() const {
return _xSprite;
}
CBofRect getRect() override;
int getCels() const {
return _nCels;
}
bool isAnimated() const {
return _bAnimated;
}
void setAnimated(bool b = true);
void setCels(int nCels);
void setPosition(const CBofPoint &pos) override;
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect = nullptr, int /*nMaskColor*/ = -1) override;
void setProperty(const CBofString &sProp, int nVal) override;
int getProperty(const CBofString &sProp) override;
int getFrameRate() const {
return _nMaxFrameRate;
}
void setFrameRate(int nFR) {
_nMaxFrameRate = nFR;
}
uint32 _nLastUpdate;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,157 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/storage_dev_bmp.h"
#include "bagel/spacebar/baglib/bagel.h"
namespace Bagel {
namespace SpaceBar {
CBagStorageDevBmp::CBagStorageDevBmp(CBofWindow *pParent, const CBofRect &xRect, bool bTrans)
: CBagBmpObject() {
_cSrcRect.setRect(0, 0, 0, 0);
_bTrans = bTrans;
_xSDevType = SDEV_BMP;
setRect(xRect);
_pWorkBmp = nullptr;
_nMaskColor = CBagel::getBagApp()->getChromaColor();
CBagStorageDev::setAssociateWnd(pParent);
setVisible(); // This object is visible
}
CBagStorageDevBmp::~CBagStorageDevBmp() {
// Delete any current work bmp
killWorkBmp();
}
ErrorCode CBagStorageDevBmp::attach() {
_nMaskColor = CBagel::getBagApp()->getChromaColor();
return CBagStorageDev::attach();
}
ErrorCode CBagStorageDevBmp::detach() {
killWorkBmp();
return CBagStorageDev::detach();
}
ErrorCode CBagStorageDevBmp::setBackground(CBofBitmap *pBmp) {
if (pBmp != nullptr) {
setBitmap(pBmp);
setWorkBmp();
} else {
// Hope and pray that this is the right thing to do
if (getBitmap()) {
delete getBitmap();
}
setBitmap(nullptr);
killWorkBmp();
}
return _errCode;
}
ErrorCode CBagStorageDevBmp::setWorkBmp() {
// Delete any previous work area
killWorkBmp();
CBofBitmap *pBmp = getBackground();
if (pBmp != nullptr) {
_pWorkBmp = new CBofBitmap(pBmp->width(), pBmp->height(), pBmp->getPalette());
pBmp->paint(_pWorkBmp);
}
return _errCode;
}
ErrorCode CBagStorageDevBmp::killWorkBmp() {
delete _pWorkBmp;
_pWorkBmp = nullptr;
return _errCode;
}
ErrorCode CBagStorageDevBmp::loadFileFromStream(CBagIfstream &fpInput, const CBofString &sWldName, bool bAttach) {
setFileName(sWldName);
setRefName(sWldName);
return CBagStorageDev::loadFileFromStream(fpInput, sWldName, bAttach);
}
void CBagStorageDevBmp::onLButtonDown(uint32 nFlags, CBofPoint *xPoint, void *info) {
CBagStorageDev::onLButtonDown(nFlags, xPoint, info);
}
void CBagStorageDevBmp::onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void *info) {
CBagStorageDev::onLButtonUp(nFlags, xPoint, info);
}
const CBofPoint CBagStorageDevBmp::devPtToViewPort(const CBofPoint &xPoint) {
// Get the storage device rect
CBofRect SDevDstRect = getRect();
// move point relative to storage device top, left
CBofPoint p;
p.x = xPoint.x - SDevDstRect.left;
p.y = xPoint.y - SDevDstRect.top;
return p;
}
ErrorCode CBagStorageDevBmp::update(CBofBitmap *pBmp, CBofPoint /*xPoint*/, CBofRect * /*pSrcRect*/, int /*nMaskColor*/) {
// if this object is visible
if (isVisible() && isAttached()) {
// Paint the storage device
CBofBitmap *pSrcBmp = getBitmap();
if (pSrcBmp != nullptr) {
assert(getWorkBmp() != nullptr);
// Erase everything from the background
getWorkBmp()->paint(pSrcBmp);
// Paint all the objects to the background
CBofRect r = pSrcBmp->getRect();
paintStorageDevice(nullptr, pSrcBmp, &r);
// Paint child storage devices
paintFGObjects(pSrcBmp);
// Paint to screen
if (_bTrans)
pSrcBmp->paint(pBmp, getPosition().x, getPosition().y, nullptr, _nMaskColor);
else
pSrcBmp->paint(pBmp, getPosition().x, getPosition().y, nullptr, -1);
}
}
// Set the firstpaint flag and attach objects to allow for immediate run objects to run
if (_bFirstPaint) {
_bFirstPaint = false;
attachActiveObjects();
}
return _errCode;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,108 @@
/* 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 BAGEL_BAGLIB_STORAGE_DEV_BMP_H
#define BAGEL_BAGLIB_STORAGE_DEV_BMP_H
#include "bagel/spacebar/baglib/bmp_object.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
namespace Bagel {
namespace SpaceBar {
class CBagStorageDevBmp : public CBagBmpObject, public CBagStorageDev {
protected:
int _nMaskColor;
CBofPoint _xCursorLocation; // Current cursor location in bmp.
CBofRect _cSrcRect;
bool _bTrans;
CBofBitmap *_pWorkBmp;
public:
CBagStorageDevBmp(CBofWindow *pParent = nullptr, const CBofRect &xRect = CBofRect(), bool bTrans = true);
virtual ~CBagStorageDevBmp();
CBofBitmap *getWorkBmp() const {
return _pWorkBmp;
}
ErrorCode setWorkBmp();
ErrorCode killWorkBmp();
CBofRect getRect() override {
return CBagStorageDev::getRect();
}
void setRect(const CBofRect &xRect) override {
CBagStorageDev::setRect(xRect);
}
CBofPoint getPosition() override {
return CBagStorageDev::getPosition();
}
void setPosition(const CBofPoint &pos) override {
CBagStorageDev::setPosition(pos);
}
bool getTransparent() const {
return _bTrans;
}
void setTransparent(bool bTrans = true) override {
_bTrans = bTrans;
}
ErrorCode setBackground(CBofBitmap *pBmp) override;
CBofBitmap *getBackground() override {
return getBitmap();
}
ErrorCode loadFileFromStream(CBagIfstream &fpInput, const CBofString &sWldName, bool bAttach = true) override;
bool isAttached() override {
return CBagBmpObject::isAttached();
}
virtual bool paintFGObjects(CBofBitmap *) {
return true;
}
ErrorCode attach() override;
ErrorCode detach() override;
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect = nullptr, int nMaskColor = -1) override;
/**
* Called on the mouse left button up of the bagbmobj
* and redirected to the lbutton up of the CBagStorageDev
*/
void onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void *info) override;
/**
* Called on the mouse left button down of the bagbmobj
* and redirected to the lbutton down of the CBagStorageDev
*/
void onLButtonDown(uint32 nFlags, CBofPoint *xPoint, void *info = nullptr) override;
const CBofPoint devPtToViewPort(const CBofPoint &xPoint) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
/* 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 BAGEL_BAGLIB_STORAGE_DEV_WIN_H
#define BAGEL_BAGLIB_STORAGE_DEV_WIN_H
#include "bagel/spacebar/boflib/gui/dialog.h"
#include "bagel/spacebar/boflib/list.h"
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/baglib/save_game_file.h"
namespace Bagel {
namespace SpaceBar {
#define SDEV_UNDEF 00
#define SDEV_WND 11
#define SDEV_DLG 22
#define SDEV_BMP 33
#define SDEV_PDA 44
#define SDEV_WIELD 55
#define SDEV_CLOSEP 66
#define SDEV_GAMEWIN 77
#define SDEV_ZOOMPDA 88
/**
* CResource is an encapsulation of resources.
*/
class CResource {
private:
const char *_lpszResourceName;
uint32 _nResId;
public:
CResource() {
_lpszResourceName = nullptr;
_nResId = 0;
}
void setResource(const char *lpszResourceName) {
_lpszResourceName = lpszResourceName;
}
void setResource(uint32 nResId) {
_nResId = nResId;
}
const char *getResourceName() const {
return _lpszResourceName;
}
uint32 getResourceId() const {
return _nResId;
}
};
// Filter function function prototype.
typedef bool (*FilterFunction)(uint16 nFilterId, CBofBitmap *, CBofRect *);
/**
* CBagPanWindow is a window that contains a slide bitmap object. It has specialize
* functions for handling slide bitmaps and slide objects.
*/
class CBagStorageDev : public CBagParseObject {
public:
enum MouseActivity {
kMouseNONE = 0x0000, kMouseDRAGGING = 0x0001
};
private:
CBofString _sName; // Name of this storage device
CBofString _sBackgroundName; // Name of this storage devices background
CBofString _sPrevSDev; // Name of the previous storage device
CBofRect _cDestRect; // Position of storage device
CBofPoint _xPrevLocation; // Previous view location in bmp.
CBagObject *_pLActiveObject; // The last object selected on mouse down
// CBagObject *_pRActiveObject; // The last object selected on mouse down
CBofList<CBagObject *> *_pObjectList; // Objects to be painted to the pan
CBofList<CBagExpression *> *_pExpressionList; // Condition for painting to the pan
CBofWindow *_pAssociateWnd; // Sounds need a window
MouseActivity _nCurrMouseActivity; // What is up with the mouse currently
uint16 _nExitOnEdge; // Non zero if SDev should be closed when an outside edge is clicked on, and and prev sdev is set, _nExitOnEdge is the thickness of the edge
uint16 _nFilterId; // Filter id number 0 for normal view
uint16 _nFadeId; // Fade id number 0 for no fade in
uint16 _nDiskID;
protected:
uint16 _xSDevType; // Type of storage device
static CBofPoint *_xCursorLocation; // Current cursor location in bmp.
static CBofRect *gRepaintRect;
static bool _bHandledUpEvent; // Hack to stop
static bool _hidePdaFl;
FilterFunction _pBitmapFilter; // Pointer to the bitmap filter.
bool _bForeignList : true; // True if setObjectList has been called
bool _bCloseOnOpen : true; // True if other SDev should be closed when this is opened
bool _bCloseup : true; // true if is a closeup (includes CIC, or CHAT)
bool _bCIC : true; // true if is a CIC
bool _bCustom : true; // true if is a hand coded closeup
bool _bFirstPaint : true; // run object stuff
static bool _bPanPreFiltered; // Let pda know if screens been prefiltered
static bool _bDirtyAllObjects; // Dirty all objects in prefilter?
static bool _bPreFilter;
int _nFloatPages; // The number of pages required to display all floating objects
public:
CBagStorageDev();
virtual ~CBagStorageDev();
virtual ErrorCode preFilter(CBofBitmap *pBmp, CBofRect *pRect, CBofList<CBagObject *> *pList = nullptr);
static void initialize();
static void shutdown();
/**
* Make all the objects in a list dirty
*/
void makeListDirty(CBofList<CBagObject *> *pList);
void setDiskID(uint16 nDiskID) {
_nDiskID = nDiskID;
}
uint16 getDiskID() const {
return _nDiskID;
}
virtual ErrorCode setloadFilePos(const CBofPoint) {
return ERR_NONE;
}
bool isCloseup() const {
return _bCloseup;
}
void setCloseup(bool b = true) {
_bCloseup = b;
}
// Set true if sdef is "AS CIC"
bool isCIC();
void setCIC(bool b = true) {
_bCIC = b;
}
// Set to true if this is a hand coded closeup
bool isCustom() const {
return _bCustom;
}
void setCustom(bool b = true) {
_bCustom = b;
}
int getDeviceType() const {
return _xSDevType;
}
int getObjectCount();
CBagObject *getObjectByPos(int nIndex);
CBagObject *getObject(int nRefId, bool bActiveOnly = false);
CBagObject *getObject(const CBofPoint &xPoint, bool bActiveOnly = false);
CBagObject *getObject(const CBofString &sName, bool bActiveOnly = false);
CBagObject *getObjectByType(const CBofString &sType, bool bActiveOnly = false);
static CBofPoint &getLastCursorLocation() {
return *_xCursorLocation;
}
CBofList<CBagObject *> *getObjectList() const {
return _pObjectList;
}
void setObjectList(CBofList<CBagObject *> *pOList, CBofList<CBagExpression *> *pEList = nullptr);
bool contains(CBagObject *pObj, bool bActive = true);
// virtual CBofRect getLocation() { return CBofRect(); }
virtual CBofRect getRect() {
return _cDestRect;
}
virtual void setRect(const CBofRect &xRect) {
_cDestRect = xRect;
}
virtual CBofPoint getPosition() {
return _cDestRect.topLeft();
}
virtual void setPosition(const CBofPoint &pos);
virtual ErrorCode addObject(CBagObject *pObj, int nPos = 0); // Add a new object
virtual ErrorCode activateLocalObject(CBagObject *pObj);
virtual ErrorCode activateLocalObject(const CBofString &sName);
virtual ErrorCode attachActiveObjects();
virtual ErrorCode removeObject(CBagObject *pRObj);
virtual ErrorCode deactivateLocalObject(CBagObject *pObj);
virtual ErrorCode deactivateLocalObject(const CBofString &sName);
virtual ErrorCode detachActiveObjects();
virtual void setHelpFilename(const CBofString &) {
}
const CBofString &getName() const {
return _sName;
}
void setName(const CBofString &str) {
_sName = str;
}
void setFilterId(uint16 nId) {
_nFilterId = nId;
}
uint16 getFilterId() const {
return _nFilterId;
}
void setFadeId(uint16 nId) {
_nFadeId = nId;
}
uint16 getFadeId() const {
return _nFadeId;
}
const CBofString &getPrevSDev() const {
return _sPrevSDev;
}
const CBofPoint getPrevLoc() const {
return _xPrevLocation;
}
void setPrevSDev(const CBofString &str) {
_sPrevSDev = str;
}
bool getCloseOnOpen() const {
return _bCloseOnOpen;
}
void setCloseOnOpen(bool bVal) {
_bCloseOnOpen = bVal;
}
uint16 getExitOnEdge() const {
return _nExitOnEdge;
}
void setExitOnEdge(uint16 nVal) {
_nExitOnEdge = nVal;
}
CBagObject *getLActiveObject() const {
return _pLActiveObject;
}
// CBagObject* GetRActiveObject() { return _pRActiveObject; }
ErrorCode setLActiveObject(CBagObject *pObj) {
_pLActiveObject = pObj;
return ERR_NONE;
}
virtual ErrorCode onLActiveObject(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr);
MouseActivity getLActivity() const {
return _nCurrMouseActivity;
}
void setLActivity(MouseActivity ma) {
_nCurrMouseActivity = ma;
}
ErrorCode paintStorageDevice(CBofWindow *pWnd, CBofBitmap *pBmp = nullptr, CBofRect * = nullptr);
// The associated window describes which window to get screen information from and
// where to paint objects and most importantly what info to send to the callbacks
virtual void setAssociateWnd(CBofWindow *pWnd) {
_pAssociateWnd = pWnd;
}
virtual CBofWindow *getAssociateWnd() {
return _pAssociateWnd;
}
ParseCodes setInfo(CBagIfstream &fpInput) override; // This function call the pure virt set background
virtual ErrorCode setBackground(CBofBitmap *pBmp) = 0; // This could be eliminated but is kept in to insure good class usage
virtual CBofBitmap *getBackground() = 0; // Think about it, you can figure this out
const CBofString &getBackgroundName() const {
return _sBackgroundName;
}
ErrorCode attach() override; // This function attaches the background and necessary bitmaps
ErrorCode detach() override; // This function attaches the background and necessary bitmaps
virtual ErrorCode close();
virtual ErrorCode loadObjects();
virtual ErrorCode releaseObjects();
virtual ErrorCode noObjectsUnderMouse();
virtual const CBofPoint devPtToViewPort(const CBofPoint &xPoint) {
return xPoint;
}
virtual const CBofPoint viewPortToDevPt(const CBofPoint &xPoint) {
return xPoint;
}
virtual ErrorCode loadFile(const CBofString &sWldName);
virtual ErrorCode loadFileFromStream(CBagIfstream &fpInput, const CBofString &sWldName, bool bAttach = true);
virtual void onMouseMove(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr);
virtual ErrorCode onMouseOver(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr);
virtual void onLButtonDown(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr);
virtual void onLButtonUp(uint32 /*nFlags*/, CBofPoint */*xPoint*/, void * = nullptr);
virtual ErrorCode onCursorUpdate(int /*nCurrObj*/) {
return ERR_NONE;
}
virtual CBagObject *onNewSpriteObject(const CBofString &sInit);
virtual CBagObject *onNewBitmapObject(const CBofString &sInit);
virtual CBagObject *onNewTextObject(const CBofString &sInit);
virtual CBagObject *onNewLinkObject(const CBofString &sInit);
virtual CBagObject *onNewRPObject(const CBofString &sInit);
virtual CBagObject *onNewEDObject(const CBofString &sInit);
virtual CBagObject *onNewDosObject(const CBofString &sInit);
virtual CBagObject *onNewSoundObject(const CBofString &sInit);
virtual CBagObject *onNewButtonObject(const CBofString &sInit);
virtual CBagObject *onNewCharacterObject(const CBofString &sInit);
virtual CBagObject *onNewMovieObject(const CBofString &);
virtual CBagObject *onNewCommandObject(const CBofString &sInit);
virtual CBagObject *onNewAreaObject(const CBofString &sInit);
virtual CBagObject *onNewExpressionObject(const CBofString &sInit);
virtual CBagObject *onNewVariableObject(const CBofString &sInit);
virtual CBagObject *onNewUserObject(const CBofString &sInit);
virtual CBagObject *onNewThingObject(const CBofString &sInit);
// Call to arrange floating object, override to customize layout
virtual CBofPoint arrangeFloater(CBofPoint &nPos, CBagObject *pObj);
// Set and Get the number of pages required to display all floating objects
int getNumFloatPages() const {
return _nFloatPages;
}
void setNumFloatPages(int nFloatPages) {
_nFloatPages = nFloatPages;
}
// Correctly set the filter function for the storage device.
//
void onSetFilter(bool (*filterFunction)(uint16 nFilterId, CBofBitmap *, CBofRect *));
// Get a pointer to the filter function
//
FilterFunction getFilter();
// Predicate to test if this storage device is filtered.
//
bool isFiltered() const {
return _nFilterId != 0;
}
// Provide a method to get at the above vars
static void setDirtyAllObjects(bool b) {
_bDirtyAllObjects = b;
}
static bool getDirtyAllObjects() {
return _bDirtyAllObjects;
}
// Provide a method to let PDA know that it should update everything
static void setPreFiltered(bool b = true) {
_bPanPreFiltered = b;
}
static bool getPreFiltered() {
return _bPanPreFiltered;
}
// We won't always call the prefilter, just when explicitly instructed to.
static bool preFilterPan() {
return _bPreFilter;
}
static void setPreFilterPan(bool b = true) {
_bPreFilter = b;
_bDirtyAllObjects = b;
}
};
class CBagEventSDev;
//
// CBagStorageDevWnd -
// CBagPanWindow is a window that contains a slide bitmap object. It has specialize
// functions for handling slide bitmaps and slide objects.
//
class CBagStorageDevWnd : public CBofWindow, public CBagStorageDev {
private:
//bool _bMadeSelection;
bool _bOnUpdate;
CBofBitmap *_pWorkBmp;
CBofString _sHelpFileName; // Name of the help file for this device
public:
static CBagEventSDev *_pEvtSDev; // Pointer to the Event Storage Device
CBagStorageDevWnd();
virtual ~CBagStorageDevWnd();
static void initialize() {
_pEvtSDev = nullptr;
}
ErrorCode attach() override; // This function attaches the background and necessary bitmaps
ErrorCode detach() override; // This function attaches the background and necessary bitmaps
ErrorCode close() override;
virtual ErrorCode runModal(CBagObject *pObj);
void onTimer(uint32 nEventID) override;
void setOnUpdate(bool bVal = true) {
_bOnUpdate = bVal;
}
bool getOnUpdate() const {
return _bOnUpdate;
}
virtual ErrorCode paintScreen(CBofRect *pRect = nullptr);
virtual ErrorCode paintObjects(CBofList<CBagObject *> *list, CBofBitmap *pBmp,
CBofRect &viewOffsetRect, CBofList<CBofRect> * = nullptr, bool tempVar = true);
virtual CBofRect getLocation() {
return getWindowRect();
}
ErrorCode setBackground(CBofBitmap *pBmp) override;
CBofBitmap *getBackground() override {
return getBackdrop();
}
virtual CBofBitmap *getWorkBmp() {
return _pWorkBmp;
}
ErrorCode loadFile(const CBofString &sFile) override;
virtual const CBofString &getHelpFilename() {
return _sHelpFileName;
}
void setHelpFilename(const CBofString &s) override {
_sHelpFileName = s;
}
virtual ErrorCode onRender(CBofBitmap *pBmp, CBofRect *pRect = nullptr);
void onPaint(CBofRect *) override;
void onMainLoop() override;
void onClose() override;
void onMouseMove(uint32 nFlags, CBofPoint *, void * = nullptr) override;
void onLButtonDown(uint32 nFlags, CBofPoint *point, void * = nullptr) override;
void onLButtonUp(uint32 nFlags, CBofPoint *point, void * = nullptr) override;
void onKeyHit(uint32 lKey, uint32 nRepCount) override;
protected:
virtual ErrorCode setWorkBmp();
virtual ErrorCode killWorkBmp();
};
/**
* CBagStorageDevDlg is a window that contains a slide bitmap object.
* It has specialize functions for handling slide bitmaps and slide objects.
*/
class CBagStorageDevDlg : public CBofDialog, public CBagStorageDev {
private:
//bool _bMadeSelection;
CBofString _sHelpFileName; // Name of the help file for this device
public:
CBagStorageDevDlg();
virtual ErrorCode paintScreen(CBofRect *pRect = nullptr);
ErrorCode paintObjects(CBofList<CBagObject *> *list, CBofBitmap *pBmp,
CBofRect &viewOffsetRect, CBofList<CBofRect> * = nullptr, bool tempVar = true);
ErrorCode paintObjects(CBofList<CBagObject *> *list, CBofBitmap *pBmp) {
CBofRect emptyRect;
return paintObjects(list, pBmp, emptyRect);
}
virtual CBofRect getLocation() {
return getWindowRect();
}
ErrorCode setBackground(CBofBitmap *pBmp) override {
if (pBmp)
return setBackdrop(pBmp);
killBackdrop();
return ERR_NONE;
}
CBofBitmap *getBackground() override {
return getBackdrop();
}
ErrorCode loadFile(const CBofString &sFile) override;
ErrorCode create(const char *pszName, CBofRect *pRect, CBofWindow *pParent, uint32 nControlID = 0) override;
ErrorCode attach() override; // This function attaches the background and necessary bitmaps
ErrorCode close() override;
virtual const CBofString &getHelpFilename() {
return _sHelpFileName;
}
void setHelpFilename(const CBofString &s) override {
_sHelpFileName = s;
}
void onMainLoop() override;
virtual ErrorCode onRender(CBofBitmap *pBmp, CBofRect *pRect = nullptr);
void onPaint(CBofRect *) override;
void onClose() override;
void onMouseMove(uint32 nFlags, CBofPoint *, void * = nullptr) override;
void onLButtonDown(uint32 nFlags, CBofPoint *point, void * = nullptr) override;
void onLButtonUp(uint32 nFlags, CBofPoint *point, void * = nullptr) override;
};
/**
* Tracks all the storage devices
*/
class CBagStorageDevManager : public CBofObject {
private:
static int nSDevMngrs;
CBofList<CBagStorageDev *> _xStorageDeviceList;
public:
CBagStorageDevManager();
~CBagStorageDevManager();
ErrorCode registerStorageDev(CBagStorageDev *pSDev);
ErrorCode unregisterStorageDev(CBagStorageDev *pSDev);
ErrorCode releaseStorageDevices();
int getObjectValue(const CBofString &sObject, const CBofString &sProperty);
void setObjectValue(const CBofString &sObject, const CBofString &sProperty, int nValue);
int getNumStorageDevices() const {
return _xStorageDeviceList.getCount();
}
CBagStorageDev *getStorageDevice(int nIndex) {
return _xStorageDeviceList[nIndex];
}
CBagStorageDev *getStorageDeviceContaining(const CBofString &sName);
CBagStorageDev *getStorageDeviceContaining(CBagObject *pObj);
CBagStorageDev *getStorageDevice(const CBofString &sName);
bool moveObject(const CBofString &sDstName, const CBofString &sSrcName, const CBofString &sObjName);
bool addObject(const CBofString &sDstName, const CBofString &sObjName);
bool removeObject(const CBofString &sSrcName, const CBofString &sObjName);
void saveObjList(StObj *pObjList, int nNumEntries);
void restoreObjList(StObj *pObjList, int nNumEntries);
};
extern bool g_allowPaintFl;
extern CBagStorageDevWnd *g_lastWindow;
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,613 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/text_object.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/spacebar/baglib/zoom_pda.h"
#include "bagel/spacebar/baglib/base_pda.h"
#include "bagel/spacebar/baglib/menu_dlg.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/rp_object.h"
#include "bagel/spacebar/boflib/gfx/text.h"
namespace Bagel {
namespace SpaceBar {
extern bool g_pauseTimerFl;
CBagTextObject::CBagTextObject() : CBagObject() {
_xObjType = TEXT_OBJ;
_nDX = 80;
_nDY = 20;
_psText = nullptr;
CBagObject::setOverCursor(1); // Switch to cursor 1, 4 doesn't exist.
_nPointSize = 16;
_nFGColor = CTEXT_COLOR;
_psInitInfo = nullptr;
_bCaption = false;
_bTitle = false;
_bReAttach = false;
_nTextFont = FONT_DEFAULT;
setRPObject(nullptr);
}
CBagTextObject::~CBagTextObject() {
delete _psInitInfo;
_psInitInfo = nullptr;
CBagTextObject::detach();
}
CBofRect CBagTextObject::getRect() {
CBofPoint p = getPosition();
CBofSize s = getSize();
CBofRect r = CBofRect(p, s);
return r;
}
ErrorCode CBagTextObject::update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect, int) {
assert(isValidObject(this));
assert(pBmp != nullptr);
assert(pSrcRect != nullptr);
// assume no error
ErrorCode errorCode = ERR_NONE;
if ((pBmp != nullptr) && isAttached() && !(getText().isEmpty())) {
if (pBmp->getRect().ptInRect(pt)) {
CBofRect r(pt, pSrcRect->size());
int nPointSize = _nPointSize;
int nFormat = FORMAT_CENTER_LEFT;
if (!_bTitle) {
byte c1 = 3;
byte c2 = 9;
CBofRect cBevel;
cBevel.intersectRect(pBmp->getRect(), r);
int left = cBevel.left;
int top = cBevel.top;
int right = cBevel.right;
int bottom = cBevel.bottom;
r.left += 6;
r.top += 3;
r.right -= 5;
r.bottom -= 5;
int i;
for (i = 1; i <= 3; i++) {
pBmp->line(left + i, bottom - i, right - i, bottom - i, c1);
pBmp->line(right - i, bottom - i, right - i, top + i - 1, c1);
}
for (i = 1; i <= 3; i++) {
pBmp->line(left + i, bottom - i, left + i, top + i - 1, c2);
pBmp->line(left + i, top + i - 1, right - i, top + i - 1, c2);
}
nPointSize = 16;
nFormat = FORMAT_TOP_LEFT;
} else {
r.left += 1;
}
errorCode = paintText(pBmp, &r, getText(), mapWindowsPointSize(nPointSize), TEXT_NORMAL, _nFGColor, JUSTIFY_WRAP, nFormat, _nTextFont);
// This object does not need to be updated now...
setDirty(false);
}
}
return errorCode;
}
ErrorCode CBagTextObject::attach() {
assert(isValidObject(this));
if (!getFileName().right(4).find(".TXT") || !getFileName().right(4).find(".txt")) {
// Prevent memory leak
delete _psText;
_psText = nullptr;
// Allocate a new string
_psText = new CBofString;
CBofFile fpTextFile(getFileName());
if (!fpTextFile.errorOccurred()) {
// Allocate the buffers
uint32 nFileLen = fpTextFile.getLength();
char *pTextBuff = (char *)bofCleanAlloc(nFileLen + 1);
// Read the text file into buffers
fpTextFile.read(pTextBuff, nFileLen);
fpTextFile.close();
*_psText += pTextBuff;
if (_psInitInfo != nullptr) {
CBagVar *pVar = g_VarManager->getVariable(*_psInitInfo);
if (pVar != nullptr) {
_bReAttach = true;
_psText->replaceStr("%s", pVar->getValue());
}
}
bofFree(pTextBuff);
} else {
reportError(ERR_FOPEN, "Failed to create a CBofFile for %s", getFileName().getBuffer());
}
if (isCaption()) {
recalcTextRect(true);
}
} else {
// The Text is in the Bagel script, rather than a .txt file
// Prevent memory leak
delete _psText;
_psText = nullptr;
// Allocate a new string
_psText = new CBofString;
*_psText = getFileName();
// Replace any underscores with spaces
_psText->replaceChar('_', ' ');
recalcTextRect(false);
}
// If this guy is linked to a residue printing object, make sure he knows
// we've been attached.
CBagRPObject *pRPObj = (CBagRPObject *)getRPObject();
if (pRPObj != nullptr) {
pRPObj->setTimeSet(false);
}
return CBagObject::attach();
}
ErrorCode CBagTextObject::detach() {
assert(isValidObject(this));
delete _psText;
_psText = nullptr;
return CBagObject::detach();
}
const CBofString &CBagTextObject::getText() {
if (_psText)
return *_psText;
return getFileName();
}
void CBagTextObject::setText(const CBofString &s) {
if (_psText) {
*_psText = s;
} else {
setFileName(s);
}
recalcTextRect(!getFileName().right(4).find(".TXT") || !getFileName().right(4).find(".txt"));
}
// Takes in info and then removes the relative information and returns the info
// without the relevant info.
//
ParseCodes CBagTextObject::setInfo(CBagIfstream &istr) {
bool nObjectUpdated = false;
while (!istr.eof()) {
istr.eatWhite();
char ch = (char)istr.peek();
switch (ch) {
//
// VAR var - var is a BAGEL CBagVar variable (replaces all %s in text)
//
case 'V': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
// Need to use this field, so no one else can
assert(_psInitInfo == nullptr);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("VAR")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
setInitInfo(sStr);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// SIZE n - n point size of the txt
//
case 'S': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("SIZE")) {
istr.eatWhite();
int n;
getIntFromStream(istr, n);
_nPointSize = (byte)n;
nObjectUpdated = true;
// WORKAROUND: Reduce the font size of Cilia's full-screen log
// in ScummVM so that it fits on the screen
if (_nPointSize == 28 && istr.getSize() == 359105)
_nPointSize = 26;
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// FONT MONO or DEFAULT
//
case 'F': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("FONT")) {
istr.eatWhite();
int n;
getIntFromStream(istr, n);
_nTextFont = MapFont(n);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
// FIXME: Missing break?
}
// fallthrough
//
// AS [CAPTION] - how to run the link
//
case 'A': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("AS")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("CAPTION")) {
_bCaption = true;
nObjectUpdated = true;
} else if (!sStr.find("TITLE")) {
_bTitle = true;
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
putbackStringOnStream(istr, "AS ");
}
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// COLOR n - n color index
//
case 'C': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("COLOR")) {
int nColor;
istr.eatWhite();
getIntFromStream(istr, nColor);
setColor(nColor);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// No match return from function
//
default: {
ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
nObjectUpdated = true;
} else { // rc==UNKNOWN_TOKEN
if (nObjectUpdated)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
break;
}
}
}
return PARSING_DONE;
}
void CBagTextObject::setColor(int nColor) {
switch (nColor) {
case 0:
_nFGColor = RGB(0, 0, 0);
break; // Black
case 1:
_nFGColor = RGB(226, 50, 51);
break; // Red
case 2:
_nFGColor = RGB(255, 255, 255);
break; // Yellow
case 3:
_nFGColor = RGB(255, 255, 255);
break; // Green
case 4:
_nFGColor = RGB(255, 255, 255);
break; // Green
case 5:
_nFGColor = RGB(0, 0, 255);
break; // Blue
case 6:
_nFGColor = RGB(255, 0, 255);
break;
case 7:
_nFGColor = CTEXT_WHITE;
break; // White
case 8:
_nFGColor = CTEXT_YELLOW;
break; // Yellow (chat highlight)
default:
break;
}
}
void CBagTextObject::setProperty(const CBofString &sProp, int nVal) {
if (!sProp.find("SIZE"))
setPointSize(nVal);
else if (!sProp.find("FONT"))
setFont(MapFont(nVal));
else if (!sProp.find("COLOR"))
setColor(nVal);
else
CBagObject::setProperty(sProp, nVal);
}
int CBagTextObject::getProperty(const CBofString &sProp) {
if (!sProp.find("SIZE"))
return getPointSize();
if (!sProp.find("FONT"))
return getFont();
if (!sProp.find("COLOR"))
return getColor();
return CBagObject::getProperty(sProp);
}
bool CBagTextObject::runObject() {
char szLocalBuff[256];
CBofString sStr(szLocalBuff, 256);
if (_bCaption && isImmediateRun()) {
// Re-attach this object to get any change in a variable
// (Must be using the VAR token).
if (_bReAttach) {
attach();
}
CBagel *pApp = CBagel::getBagApp();
if (pApp != nullptr) {
CBagMasterWin *pWin = pApp->getMasterWnd();
if (pWin != nullptr) {
CBagStorageDevWnd *pParent = pWin->getCurrentStorageDev();
CBofRect cRect(80, 10, 80 + 480 /*- 1 */, 10 + getRect().height() - 1 + 5);
CBofPoint cPoint(0, 0);
CBofPalette *pPal = pApp->getPalette();
CBofBitmap cBmp(cRect.width(), cRect.height(), pPal);
cBmp.fillRect(nullptr, pPal->getNearestIndex(RGB(92, 92, 92)));
CBagMenuDlg cDlg;
cDlg.createDlg(pParent, pPal, &cRect);
update(cDlg.getBackdrop(), cPoint, &cRect);
sStr = "BPDA_WLD";
CBagPDA *pPDA = (CBagPDA *)g_SDevManager->getStorageDevice(sStr);
// If we're in the zoom pda then put this box at the
// bottom of the zoom rect.
sStr = "BPDAZ_WLD";
SBZoomPda *pPDAZ = (SBZoomPda *)g_SDevManager->getStorageDevice(sStr);
if (pPDAZ && pPDAZ->getZoomed() == true) {
CBofRect zRect = pPDAZ->getViewRect();
assert(zRect.height() > 0 && zRect.height() < 480);
assert(zRect.width() > 0 && zRect.width() < 640);
cDlg.move(80, zRect.bottom - cRect.height(), true); // xxx
} else if ((pPDA != nullptr) && (pPDA->isActivated() || pPDA->isActivating())) {
cDlg.move(80, 10, true);
} else {
int x = 80;
int y = 360 + 10 - cRect.height();
cDlg.move(x, y, true);
}
g_pauseTimerFl = true;
cDlg.doModal();
g_pauseTimerFl = false;
}
}
}
return false;
}
int MapFont(int nFont) {
if (nFont == 0)
return FONT_MONO;
return FONT_DEFAULT;
}
void CBagTextObject::onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void *pv) {
// If there's a residue printing object, then hand this guy off to
// him, otherwise, call back to Cbagobj.
CBagRPObject *pRPObj = (CBagRPObject *)getRPObject();
if (pRPObj) {
pRPObj->onLButtonUp(nFlags, xPoint, pv);
return;
}
CBagObject::onLButtonUp(nFlags, xPoint, pv);
}
void CBagTextObject::recalcTextRect(bool bTextFromFile) {
CBofRect ViewRect; // The rect of the area where objects are displayed
CBofSize cDisplaySize; // Size of rect needed to display font
CBofSize cSize; // Size of rect needed to display font
assert(_psText != nullptr);
// The window where the object are displayed
CBagPanWindow *pPanWin = (CBagPanWindow *)(CBagel::getBagApp()->getMasterWnd()->getCurrentGameWindow());
if (bTextFromFile) {
if (pPanWin->getDeviceType() == SDEV_GAMEWIN) {
ViewRect = pPanWin->getViewPort();
} else {
ViewRect = pPanWin->getClientRect();
}
}
if (ViewRect.isRectEmpty()) {
ViewRect.setRect(80, 10, 480 + 80 - 1, 360 + 10 - 1);
}
// Get the area spanned by the text (i.e. Get the pixel width and
// height of the text string).
CBofRect tmpRect = ViewRect;
if (!_bTitle) {
// Exactly match the width used in displayTextEx
tmpRect.left += 5;
tmpRect.right = (ViewRect.right == 640 ? PAN_AREA_WIDTH : ViewRect.right) - 5;
}
CBofRect textRect = calculateTextRect(tmpRect, _psText, _nPointSize, getFont());
CBofSize stTextSize(textRect.right, textRect.bottom);
if (bTextFromFile) {
// Add fudge factor to make sure that all the text will fit, and not
// get cut off. This may cause an extra blank line of text in some
// captions, but tough diddles, it's still better than truncating
// some text.
cSize.cx = stTextSize.cx;
cSize.cy = stTextSize.cy;
} else {
cSize.cx = stTextSize.cx + 9;
cSize.cy = stTextSize.cy + (_bTitle ? 0 : 7);
setSize(cSize);
}
if (bTextFromFile) {
cDisplaySize.cx = ViewRect.width();
cDisplaySize.cy = cSize.cy;
// If for some reason (CIC, CHAT) we got too large
// a viewrect, cut it back to the correct width
if (cDisplaySize.cx > PAN_AREA_WIDTH)
cDisplaySize.cx = PAN_AREA_WIDTH;
// Buffer the size a little for spacing etc.
cDisplaySize.cx -= 5;
// While the text is wider then the view area
while (cSize.cx > cDisplaySize.cx) {
// Increment Display Height to account for another line
cDisplaySize.cy += cSize.cy;
// Decrement the size of text by the width of one line
cSize.cx -= cDisplaySize.cx;
}
// Add a little space at the bottom
cDisplaySize.cy += 5;
setSize(cDisplaySize);
}
}
void CBagTextObject::setPSText(CBofString *p) {
assert(isValidObject(this));
delete _psText;
_psText = nullptr;
if (p != nullptr) {
_psText = new CBofString(*p);
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,151 @@
/* 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 BAGEL_BAGLIB_TEXT_OBJECT_H
#define BAGEL_BAGLIB_TEXT_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/boflib/gfx/text.h"
namespace Bagel {
namespace SpaceBar {
// local prototypes...
int MapFont(int nFont);
/**
* CBagTextObject is an object that can be place within the slide window.
*/
class CBagTextObject : public CBagObject {
private:
CBofString *_psInitInfo; // Aux info
COLORREF _nFGColor;
int16 _nDX;
int16 _nDY;
byte _nPointSize;
int _nTextFont;
CBagObject *_pRPObject;
protected:
bool _bCaption : true;
bool _bTitle : true;
bool _bReAttach : true;
CBofString *_psText;
public:
CBagTextObject();
virtual ~CBagTextObject();
CBofRect getRect() override;
CBofSize getSize() const {
return CBofSize(_nDX, _nDY);
}
void setSize(const CBofSize &xSize) override {
_nDX = (int16)xSize.cx;
_nDY = (int16)xSize.cy;
}
int getPointSize() const {
return _nPointSize;
}
void setPointSize(int xSize) {
assert(xSize >= 0 && xSize <= 255);
_nPointSize = (byte)xSize;
}
int getColor() const {
return 0;
}
void setColor(int nColor);
// Font support for text objects
int getFont() const {
return _nTextFont;
}
void setFont(int nFont) {
_nTextFont = nFont;
}
bool runObject() override;
const CBofString *getInitInfo() const override {
return _psInitInfo;
}
void setInitInfo(const CBofString &info) override {
delete _psInitInfo;
_psInitInfo = new CBofString();
*_psInitInfo = info;
}
CBofString *getPSText() const {
return _psText;
}
void setPSText(CBofString *p);
const CBofString &getText();
void setText(const CBofString &s);
/**
* Calculate the required bounds to display text
*/
void recalcTextRect(bool bTextFromFile);
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect * /*pSrcRect*/ = nullptr, int /*nMaskColor*/ = -1) override;
ErrorCode attach() override;
ErrorCode detach() override;
ParseCodes setInfo(CBagIfstream &istr) override;
void setProperty(const CBofString &sProp, int nVal) override;
int getProperty(const CBofString &sProp) override;
bool isCaption() const {
return _bCaption;
}
void setTitle(bool b = true) {
_bTitle = b;
}
bool isTitle() const {
return _bTitle;
}
// Extra stuff to handle mouse downs on floaters in the log pda/residue printing code.
void onLButtonUp(uint32, CBofPoint *, void * = nullptr) override;
void setRPObject(CBagObject *prp) {
_pRPObject = prp;
}
CBagObject *getRPObject() const {
return _pRPObject;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,41 @@
/* 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 BAGEL_BAGLIB_THING_OBJECT_H
#define BAGEL_BAGLIB_THING_OBJECT_H
#include "bagel/spacebar/baglib/character_object.h"
namespace Bagel {
namespace SpaceBar {
class CBagThingObject : public CBagCharacterObject {
public:
CBagThingObject() {
_xObjType = THING_OBJ;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,277 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/time_object.h"
#include "bagel/boflib/log.h"
namespace Bagel {
namespace SpaceBar {
CBagTimeObject::CBagTimeObject() : CBagObject() {
_xObjType = SPRITE_OBJ;
_xDig1 = nullptr;
_xDig2 = nullptr;
_xColon = nullptr;
_xDig3 = nullptr;
_xDig4 = nullptr;
_nCels = 1;
CBagObject::setOverCursor(1);
setTimeless(true);
}
CBagTimeObject::~CBagTimeObject() {
CBagTimeObject::detach();
}
ErrorCode CBagTimeObject::attach() {
CBofPoint p = CBagObject::getPosition();
_xDig1 = new CBofSprite();
if (_xDig1->loadSprite(getFileName(), getCels()) != 0 && (_xDig1->width() != 0) && (_xDig1->height() != 0)) {
_xDig1->setAnimated(false);
_xDig1->setPosition(p.x, p.y);
p.offset(_xDig1->width(), 0);
} else {
reportError(ERR_FOPEN, "Could Not Open Dig1 Sprite: %s", _xDig1->getFileName());
}
_xDig2 = new CBofSprite();
if (_xDig2->loadSprite(getFileName(), getCels()) != 0 && (_xDig2->width() != 0) && (_xDig2->height() != 0)) {
_xDig2->setAnimated(false);
_xDig2->setPosition(p.x, p.y);
p.offset(_xDig2->width(), 0);
} else {
reportError(ERR_FOPEN, "Could Not Open Dig2 Sprite: %s", _xDig2->getFileName());
}
_xColon = new CBofSprite();
if (_xColon->loadSprite(getFileName(), getCels()) != 0 && (_xColon->width() != 0) && (_xColon->height() != 0)) {
_xColon->setAnimated(false);
// The time sprite should start with 0 and go to 9 followed by the :
_xColon->setCel(_nCels - 1);
_xColon->setPosition(p.x, p.y);
p.offset(_xColon->width(), 0);
} else {
reportError(ERR_FOPEN, "Could Not Open Colon Sprite: %s", _xColon->getFileName());
}
_xDig3 = new CBofSprite();
if (_xDig3->loadSprite(getFileName(), getCels()) != 0 && (_xDig3->width() != 0) && (_xDig3->height() != 0)) {
_xDig3->setAnimated(false);
_xDig3->setPosition(p.x, p.y);
p.offset(_xDig3->width(), 0);
} else {
reportError(ERR_FOPEN, "Could Not Open Dig3 Sprite: %s", _xDig3->getFileName());
}
_xDig4 = new CBofSprite();
if (_xDig4->loadSprite(getFileName(), getCels()) != 0 && (_xDig4->width() != 0) && (_xDig4->height() != 0)) {
_xDig4->setAnimated(false);
_xDig4->setPosition(p.x, p.y);
p.offset(_xDig4->width(), 0);
} else {
reportError(ERR_FOPEN, "Could Not Open Dig4 Sprite: %s", _xDig4->getFileName());
}
return CBagObject::attach();
}
ErrorCode CBagTimeObject::detach() {
delete _xDig1;
_xDig1 = nullptr;
delete _xDig2;
_xDig2 = nullptr;
delete _xColon;
_xColon = nullptr;
delete _xDig3;
_xDig3 = nullptr;
delete _xDig4;
_xDig4 = nullptr;
return CBagObject::detach();
}
void CBagTimeObject::setCels(int nCels) {
_nCels = nCels;
if (_xDig1)
_xDig1->setupCels(nCels);
if (_xDig2)
_xDig2->setupCels(nCels);
if (_xColon)
_xColon->setupCels(nCels);
if (_xDig3)
_xDig3->setupCels(nCels);
if (_xDig4)
_xDig4->setupCels(nCels);
}
void CBagTimeObject::setPosition(const CBofPoint &pos) {
CBagObject::setPosition(pos);
}
CBofRect CBagTimeObject::getRect() {
CBofPoint p = getPosition();
CBofSize s;
if (_xDig1) {
s = _xDig1->getSize();
// Increase the width to accommodate all 5 sprites
s.cx = s.cx * 5;
}
return CBofRect(p, s);
}
ParseCodes CBagTimeObject::setInfo(CBagIfstream &istr) {
bool nObjectUpdated = false;
while (!istr.eof()) {
istr.eatWhite();
char ch = (char)istr.peek();
switch (ch) {
//
// +n - n number of slides in sprite
//
case '+': {
int cels;
istr.getCh();
getIntFromStream(istr, cels);
setCels(cels);
nObjectUpdated = true;
break;
}
case 'V': {
char szLocalBuff[256];
szLocalBuff[0] = '\0';
CBofString sStr(szLocalBuff, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("VALUE")) {
istr.eatWhite();
char szLocalBuff1[256];
szLocalBuff[0] = '\0';
CBofString s(szLocalBuff1, 256);
getAlphaNumFromStream(istr, s);
setVariable(s);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
// No match return from function
default: {
ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
nObjectUpdated = true;
} else {
// rc==UNKNOWN_TOKEN
if (nObjectUpdated)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
break;
}
}
}
return PARSING_DONE;
}
ErrorCode CBagTimeObject::update(CBofBitmap *pBmp, CBofPoint pt, CBofRect * /*pSrcRect*/, int) {
char szLocalBuff[256];
szLocalBuff[0] = '\0';
CBofString sTimeString(szLocalBuff, 256);
ErrorCode errorCode = ERR_NONE;
CBagVar *xVar = g_VarManager->getVariable(_sVariable);
// If everything looks good
if (isAttached() && xVar && !(xVar->getValue().isEmpty())) {
int nTimeVal = xVar->getNumValue();
sTimeString = buildString("%04d", nTimeVal);
char sDigString[2] = "0";
// Digit 1
if (_xDig1) {
sDigString[0] = sTimeString[0];
_xDig1->setCel(atoi(sDigString));
_xDig1->paintSprite(pBmp, pt.x, pt.y);
pt.offset(_xDig1->width(), 0);
}
// Digit 2
if (_xDig2) {
sDigString[0] = sTimeString[1];
_xDig2->setCel(atoi(sDigString));
_xDig2->paintSprite(pBmp, pt.x, pt.y);
pt.offset(_xDig2->width(), 0);
}
if (_xColon) {
_xColon->paintSprite(pBmp, pt.x, pt.y);
pt.offset(_xColon->width(), 0);
}
// Digit 3
if (_xDig3) {
sDigString[0] = sTimeString[2];
_xDig3->setCel(atoi(sDigString));
_xDig3->paintSprite(pBmp, pt.x, pt.y);
pt.offset(_xDig3->width(), 0);
}
// Digit 4
if (_xDig4) {
sDigString[0] = sTimeString[3];
_xDig4->setCel(atoi(sDigString));
_xDig4->paintSprite(pBmp, pt.x, pt.y);
}
}
return errorCode;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,90 @@
/* 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 BAGEL_BAGLIB_TIME_OBJECT_H
#define BAGEL_BAGLIB_TIME_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
#include "bagel/spacebar/boflib/gfx/bitmap.h"
#include "bagel/spacebar/boflib/gfx/sprite.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagTimeObject is an object that can be place within the slide window.
*/
class CBagTimeObject : public CBagObject {
private:
CBofString _sVariable;
CBofSprite *_xDig1; // x-:--
CBofSprite *_xDig2; // -x:--
CBofSprite *_xColon; // --:--
CBofSprite *_xDig3; // --:x-
CBofSprite *_xDig4; // --:-x
int _nCels;
public:
CBagTimeObject();
virtual ~CBagTimeObject();
/**
* Create all 5 sprite objects for the clock and set their positions
*/
ErrorCode attach() override;
ErrorCode detach() override;
bool isAttached() override {
return _xDig1 != nullptr;
}
/**
* Takes in info and then removes the relative information and returns the info
* without the relevant info.
*/
ParseCodes setInfo(CBagIfstream &istr) override;
CBofRect getRect() override;
int getCels() {
return _nCels;
}
void setCels(int nCels);
void setPosition(const CBofPoint &pos) override;
/**
* Read in the value of the associated variable and set the time equal
* to the first 4 digits of the variable if the variable is less the 4 digits
* the time is padded with 0's if it is greater the 4 we truncate to remaining digits
*/
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect = nullptr, int /*nMaskColor*/ = -1) override;
void setVariable(const CBofString &sProp) {
_sVariable = sProp;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,376 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/var.h"
#include "bagel/spacebar/baglib/event_sdev.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/bagel.h"
namespace Bagel {
namespace SpaceBar {
static int HASHVAR(const char *p, int l);
int CBagVarManager::nVarMngrs;
void CBagVarManager::initialize() {
nVarMngrs = 0;
}
CBagVar::CBagVar() {
setGlobal(false);
setConstant(false);
setReference(false);
setTimer(false);
setString();
setRandom(false);
g_VarManager->registerVariable(this);
}
CBagVar::CBagVar(const CBofString &sName, const CBofString &sValue, bool bAddToList) {
setConstant(false);
setReference(false);
setTimer(false);
setString();
setName(sName);
setValue(sValue);
setRandom(false);
setGlobal(false);
if (bAddToList)
g_VarManager->registerVariable(this);
}
CBagVar::~CBagVar() {
if (CBagel::getBagApp() &&
CBagel::getBagApp()->getMasterWnd() &&
CBagel::getBagApp()->getMasterWnd()->getVariableManager())
g_VarManager->unRegisterVariable(this);
}
void CBagVar::setValue(const CBofString &s) {
assert(isValidObject(this));
if (!_freeze) {
if (!s.isEmpty()) {
char c = s[0];
if (Common::isDigit(c) || c == '-')
setNumeric();
}
_sVarValue = s;
}
}
const CBofString &CBagVar::getValue() {
assert(isValidObject(this));
// WORKAROUND: If you finish the Deven7 flashback without having previously
// asked him about betting, it hangs him. Work around this by force setting
// betting to have been discussed
if (_sVarName == "BETWITHDEVEN") {
if (g_VarManager->getVariable("DEVENCODE1")->getValue() != "NOTSETYET")
// Finished flashback, so ensure betting flag is set
_sVarValue = "1";
}
// Check if these items should be replaced by the current sdev
if (!_sVarName.isEmpty() && !_sVarName.find(CURRSDEV_TOKEN)) {
if (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()) {
_sVarValue = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()->getName();
}
} else if (!_sVarName.isEmpty() && !_sVarName.find(PREVSDEV_TOKEN)) {
// Check if these items should be replaced by the previous sdev
if (CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()) {
_sVarValue = CBagel::getBagApp()->getMasterWnd()->getCurrentStorageDev()->getPrevSDev();
}
}
return _sVarValue;
}
void CBagVar::setBoolValue(bool bVal) {
assert(isValidObject(this));
if (bVal)
_sVarValue = "true";
else
_sVarValue = "false";
}
void CBagVar::setValue(int nVal) {
assert(isValidObject(this));
if (!_freeze) {
setNumeric();
Common::String tmp = Common::String::format("%d", nVal);
_sVarValue = tmp.c_str();
}
}
int CBagVar::getNumValue() {
assert(isValidObject(this));
if (isRandom())
return g_engine->getRandomNumber();
return atoi(_sVarValue);
}
void CBagVar::increment() {
assert(isValidObject(this));
if (isNumeric())
setValue(getNumValue() + 1);
}
ParseCodes CBagVar::setInfo(CBagIfstream &istr) {
assert(isValidObject(this));
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
setName(sStr);
istr.eatWhite();
if (istr.peek() == 'A') {
char sz2LocalStr[256];
sz2LocalStr[0] = 0;
sStr = CBofString(sz2LocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("AS")) {
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("TIMER")) {
setTimer();
g_VarManager->updateRegistration();
} else if (!sStr.find("RANDOM")) {
setRandom(true);
g_VarManager->updateRegistration();
} else if (!sStr.find("GLOBAL")) {
setGlobal(true);
g_VarManager->updateRegistration();
} else {
putbackStringOnStream(istr, sStr);
putbackStringOnStream(istr, "AS ");
}
} else {
putbackStringOnStream(istr, sStr);
}
}
istr.eatWhite();
if (istr.peek() == '=') {
istr.getCh();
istr.eatWhite();
getAlphaNumFromStream(istr, sStr);
setValue(sStr);
}
istr.eatWhite();
return PARSING_DONE;
}
CBagVarManager::CBagVarManager() {
++nVarMngrs;
}
CBagVarManager::~CBagVarManager() {
if (nVarMngrs) {
nVarMngrs--;
releaseVariables();
_xVarList.removeAll();
for (int i = 0; i < VAR_HASH_TABLE_SIZE; i++) {
_xVarHashList[i].removeAll();
}
}
}
static int HASHVAR(const char *p, int l) {
int h = 0;
for (int j = 0; j < l; j++) {
h += p[j];
}
h %= VAR_HASH_TABLE_SIZE;
return h;
}
ErrorCode CBagVarManager::registerVariable(CBagVar *pVar) {
_xVarList.addToTail(pVar);
return ERR_NONE;
}
// Arranges the list so that timer variables are in the front
ErrorCode CBagVarManager::updateRegistration() {
bool bFoundLastTimer = false;
int i;
// Read the timers at the beginning
for (i = 0; i < _xVarList.getCount() && !bFoundLastTimer; ++i) {
if (!_xVarList[i]->isTimer()) {
bFoundLastTimer = true;
}
}
// Make sure there are no more timers in the list
if (bFoundLastTimer) {
for (/*- i determined in previous for loop -*/; i < _xVarList.getCount(); ++i) {
if (_xVarList[i]->isTimer()) {
CBagVar *pVar = _xVarList[i];
_xVarList.remove(i);
_xVarList.addToHead(pVar);
}
}
}
return ERR_UNKNOWN;
}
ErrorCode CBagVarManager::unRegisterVariable(CBagVar *pVar) {
// Find and remove specified variable from the Var manager list
//
CBofListNode<CBagVar *> *pList = _xVarList.getTail();
while (pList != nullptr) {
if (pList->getNodeItem() == pVar) {
_xVarList.remove(pList);
break;
}
pList = pList->_pPrev;
}
// Remove it from the hash table also.
char szLocalBuff[256];
CBofString varStr(szLocalBuff, 256);
varStr = pVar->getName();
// Hash it
int nHashVal = HASHVAR(szLocalBuff, varStr.getLength());
CBofList<CBagVar *> *pVarList = &_xVarHashList[nHashVal];
// Search the hash table and remove it when we're done.
for (int i = 0; i < pVarList->getCount(); ++i) {
CBagVar *pHashVar = pVarList->getNodeItem(i);
if (pVar == pHashVar) {
pVarList->remove(i);
break;
}
}
return ERR_NONE;
}
// The timers must be at the beginning of the list
ErrorCode CBagVarManager::incrementTimers() {
volatile bool bFoundLastTimer = false;
// Read the timers at the beginning
for (int i = 0; i < _xVarList.getCount() && !bFoundLastTimer; ++i) {
CBagVar *pVar = _xVarList[i];
if (pVar->isTimer()) {
// Hack to keep the game time from exceeding 22:50
if (pVar->getName().compareNoCase("TURNCOUNT") == 0) {
if (pVar->getNumValue() == 2250) {
continue;
}
}
pVar->increment();
}
}
// Separate turn world out of event world and only execute when we
// increment the timers.
CBagEventSDev::setEvalTurnEvents(true);
return ERR_NONE;
}
ErrorCode CBagVarManager::releaseVariables(bool bIncludeGlobals) {
if (bIncludeGlobals) {
while (_xVarList.getCount()) {
CBagVar *pVar = _xVarList.removeHead();
delete pVar;
}
} else { // Do not include globals
for (int i = _xVarList.getCount() - 1; i >= 0; i--) {
CBagVar *pVar = _xVarList[i];
if (pVar && !pVar->isGlobal()) {
_xVarList.remove(i);
delete pVar;
}
}
}
return ERR_NONE;
}
CBagVar *CBagVarManager::getVariable(const CBofString &sName) {
// Use the hash table to find the variable.
char szLocalBuff[256];
CBofString varStr(szLocalBuff, 256);
varStr = sName;
int nHashVal = HASHVAR(szLocalBuff, varStr.getLength());
CBofList<CBagVar *> *pVarList = &_xVarHashList[nHashVal];
for (int i = 0; i < pVarList->getCount(); ++i) {
CBagVar *pVar = pVarList->getNodeItem(i);
if (pVar != nullptr && (pVar->getName().getLength() == sName.getLength()) && !pVar->getName().find(sName)) {
return pVar;
}
}
return nullptr;
}
void CBagVar::setName(const CBofString &s) {
_sVarName = s;
CBagel *pApp = CBagel::getBagApp();
if (pApp) {
CBagMasterWin *pMainWin = pApp->getMasterWnd();
if (!s.isEmpty() && pMainWin && pMainWin->getVariableManager()) {
char szLocalBuff[256];
CBofString varStr(szLocalBuff, 256);
varStr = _sVarName;
int nHashVal = HASHVAR(szLocalBuff, varStr.getLength());
g_VarManager->_xVarHashList[nHashVal].addToTail(this);
}
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,164 @@
/* 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 BAGEL_BAGLIB_VAR_H
#define BAGEL_BAGLIB_VAR_H
#include "bagel/spacebar/baglib/parse_object.h"
#include "bagel/boflib/string.h"
#include "bagel/spacebar/boflib/list.h"
namespace Bagel {
namespace SpaceBar {
class CBagVar : public CBagParseObject, public CBofObject {
public:
enum VARTYPE {
STRING = 0, NUMBER = 1, BOOLEAN = 2
};
private:
CBofString _sVarName; // Name of the variable
CBofString _sVarValue; // Value of the variable if not a reference
VARTYPE _xVarType; // Type of variable, string
bool _bGlobal : 1; // Is the variable a constant
bool _bConstant : 1; // Is the variable a constant
bool _bReference : 1; // Is the variable a reference to an objects state date
bool _bTimer : 1; // Is the variable updated on object timer events
bool _bRandom : 1; // Is the variable updated as a random number
bool _freeze = false;
public:
CBagVar();
CBagVar(const CBofString &sName, const CBofString &sValue, bool bAddToList);
virtual ~CBagVar();
ParseCodes setInfo(CBagIfstream &) override;
const CBofString &getName() {
return _sVarName;
}
// const CBofString& getValue() { return _sVarValue; }
const CBofString &getValue();
int getNumValue();
bool isGlobal() {
return _bGlobal;
}
bool isConstant() {
return _bConstant;
}
bool isNumeric() {
return _xVarType == NUMBER;
}
bool isBoolean() {
return _xVarType == BOOLEAN;
}
bool isString() {
return _xVarType == STRING;
}
bool isReference() {
return _bReference;
}
bool isTimer() {
return _bTimer;
}
bool isRandom() {
return _bRandom;
}
bool isFrozen() const {
return _freeze;
}
VARTYPE getType() {
return _xVarType;
}
// Whenever setting the name, add this object to the hash table.
void setName(const CBofString &s);
void setValue(const CBofString &s);
void setValue(int nVal);
void setBoolValue(bool bVal);
void setGlobal(bool bVal = true) {
_bGlobal = bVal;
}
void setConstant(bool bVal = true) {
_bConstant = bVal;
}
void setReference(bool bVal = true) {
_bReference = bVal;
}
void setTimer(bool bVal = true) {
_bTimer = bVal;
}
void setRandom(bool bVal = true) {
_bRandom = bVal;
}
void setFreeze(bool bVal = true) {
_freeze = bVal;
}
void setString() {
_xVarType = STRING;
}
void setNumeric() {
_xVarType = NUMBER;
}
void setBoolean() {
_xVarType = BOOLEAN;
}
void increment();
};
// This could be templated with the storage device manager
#define VAR_HASH_TABLE_SIZE 131
class CBagVarManager : public CBagParseObject, public CBofObject {
private:
static int nVarMngrs;
CBofList<CBagVar *> _xVarList;
public:
CBagVarManager();
virtual ~CBagVarManager();
static void initialize();
ErrorCode registerVariable(CBagVar *pVar);
ErrorCode unRegisterVariable(CBagVar *pVar);
ErrorCode updateRegistration();
ErrorCode releaseVariables(bool bIncludeGlobals = true);
ErrorCode incrementTimers();
CBagVar *getVariable(const CBofString &sName);
CBagVar *getVariable(int i) {
return _xVarList[i];
}
int getNumVars() {
return _xVarList.getCount();
}
// Use a hash table to lookup variables.
CBofList<CBagVar *> _xVarHashList[VAR_HASH_TABLE_SIZE];
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,208 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/variable_object.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/var.h"
namespace Bagel {
namespace SpaceBar {
CBagVariableObject::CBagVariableObject() : CBagObject() {
_xObjType = VAR_OBJ;
_nPointSize = 16;
_nFGColor = CTEXT_COLOR;
setVisible(true);
setTimeless(true);
}
CBagVariableObject::~CBagVariableObject() {
CBagVariableObject::detach();
}
ErrorCode CBagVariableObject::attach() {
CBagVar *xVar = g_VarManager->getVariable(getFileName());
if (xVar && !getRefName().isEmpty())
xVar->setValue(getRefName());
return CBagObject::attach();
}
ErrorCode CBagVariableObject::detach() {
return CBagObject::detach();
}
CBofRect CBagVariableObject::getRect() {
CBofPoint p = getPosition();
CBofSize s = getSize();
CBofRect r = CBofRect(p, s);
return r;
}
//
// Takes in info and then removes the relative information and returns the info
// without the relevant info.
ParseCodes CBagVariableObject::setInfo(CBagIfstream &istr) {
bool nObjectUpdated = false;
while (!istr.eof()) {
istr.eatWhite();
char ch = (char)istr.peek();
switch (ch) {
//
// SIZE n - n point size of the txt
//
case 'S': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("SIZE")) {
istr.eatWhite();
getIntFromStream(istr, _nPointSize);
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
}
break;
//
// COLOR n - n color index
//
case 'C': {
char szLocalStr[256];
szLocalStr[0] = 0;
CBofString sStr(szLocalStr, 256);
getAlphaNumFromStream(istr, sStr);
if (!sStr.find("COLOR")) {
int nColor;
istr.eatWhite();
getIntFromStream(istr, nColor);
switch (nColor) {
case 0:
_nFGColor = RGB(0, 0, 0);
break; // black
case 1:
_nFGColor = RGB(255, 0, 0);
break;
case 2:
_nFGColor = CTEXT_YELLOW;
break;
case 3:
_nFGColor = RGB(0, 255, 0);
break;
case 4:
_nFGColor = RGB(0, 255, 255);
break;
case 5:
_nFGColor = RGB(0, 0, 255);
break;
case 6:
_nFGColor = RGB(255, 0, 255);
break;
case 7:
_nFGColor = CTEXT_WHITE;
break;
default:
break;
}
nObjectUpdated = true;
} else {
putbackStringOnStream(istr, sStr);
}
break;
}
//
// No match return from function
//
default:
ParseCodes parseCode = CBagObject::setInfo(istr);
if (parseCode == PARSING_DONE) {
return PARSING_DONE;
}
if (parseCode == UPDATED_OBJECT) {
nObjectUpdated = true;
} else {
if (nObjectUpdated)
return UPDATED_OBJECT;
return UNKNOWN_TOKEN;
}
break;
}
}
return PARSING_DONE;
}
ErrorCode CBagVariableObject::update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect, int) {
ErrorCode errorCode = ERR_NONE;
CBagVar *xVar = g_VarManager->getVariable(getFileName());
if (isAttached() && xVar && !(xVar->getValue().isEmpty())) {
// FIXME: Offset for the last accessed time and # times counter in
// entryway computer terminal. Otherwise, there's no space between
// them and the preceding text
Common::String name = xVar->getName().getBuffer();
if (name.hasSuffix("_LAST") || name.hasSuffix("_TIMES"))
pt.x += 10;
// FIXME: Slight spacing out for Fleebix frequency display
if (name == "NDJAM_INNERDIAL_DISPLAY")
pt.x -= 5;
else if (name == "NDJAM_OUTERDIAL_DISPLAY")
pt.x += 5;
CBofRect r(pt, pSrcRect->size());
errorCode = paintText(pBmp, &r, xVar->getValue(), mapFontPointSize(_nPointSize), TEXT_NORMAL, _nFGColor);
// Don't need to redraw!
setDirty(false);
}
return errorCode;
}
ErrorCode CBagVariableObject::update(CBofWindow *pWnd, CBofPoint pt, CBofRect *pSrcRect, int) {
ErrorCode errorCode = ERR_NONE;
CBagVar *xVar = g_VarManager->getVariable(getFileName());
if (isAttached() && xVar && !(xVar->getValue().isEmpty())) {
CBofRect r(pt, pSrcRect->size());
errorCode = paintText(pWnd, &r, xVar->getValue(), mapFontPointSize(_nPointSize), TEXT_NORMAL, _nFGColor);
// Don't need to redraw!
setDirty(false);
}
return errorCode;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,71 @@
/* 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 BAGEL_BAGLIB_VARIABLE_OBJECT_H
#define BAGEL_BAGLIB_VARIABLE_OBJECT_H
#include "bagel/spacebar/baglib/object.h"
namespace Bagel {
namespace SpaceBar {
/**
* CBagVariableObject is an object that can be place within the slide window.
*/
class CBagVariableObject : public CBagObject {
private:
CBofSize _xSize;
int _nPointSize;
COLORREF _nFGColor;
public:
CBagVariableObject();
virtual ~CBagVariableObject();
// Return true if the Object had members that are properly initialized/de-initialized
ErrorCode attach() override;
ErrorCode detach() override;
CBofRect getRect() override;
CBofSize getSize() {
return _xSize;
}
void setSize(const CBofSize &xSize) override {
_xSize = xSize;
}
ParseCodes setInfo(CBagIfstream &istr) override;
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect, int) override;
ErrorCode update(CBofWindow *pWnd, CBofPoint pt, CBofRect *pSrcRect, int);
int mapFontPointSize(int size) const {
return size;
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,184 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/wield.h"
#include "bagel/spacebar/baglib/menu_dlg.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/sprite_object.h"
#include "bagel/spacebar/baglib/bagel.h"
namespace Bagel {
namespace SpaceBar {
int CBagWield::_nWieldCursor = -1;
CBagWield::CBagWield(CBofWindow *pParent, const CBofRect &xRect) :
CBagStorageDevBmp(pParent, xRect) {
_xSDevType = SDEV_WIELD;
_nObjects = 0; // This should be changed on the attach
_pCurrObj = nullptr;
}
CBagWield::~CBagWield() {
}
ErrorCode CBagWield::loadFile(const CBofString &sFile) {
ErrorCode errorCode = CBagStorageDev::loadFile(sFile);
return errorCode;
}
ErrorCode CBagWield::attach() {
CBagStorageDevBmp::attach();
// Take care of objects being held
int nObjects = 0;
_nObjects = 0;
for (int i = 0; i < getObjectCount(); ++i) {
CBagObject *pObj = getObjectByPos(i);
if (pObj->isActive() && (pObj->getType() == BOF_SPRITE_OBJ || pObj->getType() == BOF_BMP_OBJ)) {
if (nObjects == 0) {
nObjects++;
activateLocalObject(pObj);
} else {
pObj->detach();
}
}
}
return _errCode;
}
ErrorCode CBagWield::detach() {
CBagStorageDev::detach();
return CBagBmpObject::detach();
}
bool CBagWield::onObjInteraction(CBagObject *pObj, CBagStorageDev *pSDev) {
CBofString sObjName = pObj->getRefName();
if (sObjName.isEmpty())
return false;
// Find the storage device
if (CBagStorageDev::activateLocalObject(sObjName) != ERR_NONE)
return false;
if (pSDev->deactivateLocalObject(sObjName) != ERR_NONE) {
CBagStorageDev::deactivateLocalObject(sObjName);
return false;
}
return true;
}
ErrorCode CBagWield::activateLocalObject(CBagObject *pObj) {
ErrorCode errorCode = ERR_UNKNOWN;
if (pObj != nullptr) {
// Since we can only hold one object at a time, put the object that
// the user is currently holding into their stash (Inventory), and then
// put the new object that they are trying to pick up into their wield.
if (_nObjects == 1) {
CBagObject *pPrevObj = getCurrObj();
if (pPrevObj != nullptr) {
// Move current object to stash
g_SDevManager->moveObject("INV_WLD", getName(), pPrevObj->getRefName());
} else {
reportError(ERR_UNKNOWN, "Wielded Object has been lost");
}
// There are no objects in wield
_nObjects = 0;
}
// Add to wield
if (pObj->getMenuPtr() != nullptr) {
CBagMenu::setUniversalObjectList(pObj->getMenuPtr()->getObjectList());
}
if (pObj->getType() == SPRITE_OBJ) {
setCurrObj(pObj);
_nObjects++;
CBagSpriteObject *pSpObj = (CBagSpriteObject *)pObj;
setWieldCursor(pSpObj->getWieldCursor());
}
// Fix for sometimes getting the wield menu instead of thud's order
// menu. Do this by causing the wielded item to not have a location
// on the You icon. (It's rectangle will appear empty)
CBofPoint cPos(2056, 2056);
pObj->setPosition(cPos);
pObj->setFloating(false);
errorCode = CBagStorageDev::activateLocalObject(pObj);
}
return errorCode;
}
ErrorCode CBagWield::deactivateLocalObject(CBagObject *pObj) {
if (_nObjects == 1) {
if (pObj->getType() == SPRITE_OBJ) {
setWieldCursor(-1);
_nObjects--;
}
CBagMenu::setUniversalObjectList(nullptr);
CBagStorageDev::deactivateLocalObject(pObj);
setCurrObj(nullptr);
}
return _errCode;
}
ErrorCode CBagWield::update(CBofBitmap *pBmp, CBofPoint /*cPoint*/, CBofRect * /*pSrcRect*/, int /*nMaskColor*/) {
assert(pBmp != nullptr);
// If this object is visible
if (isVisible() && isAttached()) {
CBofBitmap *pYouIcon = getBackground();
if (pYouIcon != nullptr) {
pYouIcon->paint(pBmp, getPosition().x, getPosition().y, nullptr, DEFAULT_CHROMA_COLOR);
setDirty(false);
}
}
// Set the firstpaint flag and attach objects to allow for immediate run objects to run
if (_bFirstPaint) {
_bFirstPaint = false;
attachActiveObjects();
}
return ERR_NONE;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,74 @@
/* 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 BAGEL_BAGLIB_WIELD_H
#define BAGEL_BAGLIB_WIELD_H
#include "bagel/spacebar/baglib/storage_dev_bmp.h"
namespace Bagel {
namespace SpaceBar {
class CBagWield : public CBagStorageDevBmp {
private:
static int _nWieldCursor;
CBagObject *_pCurrObj;
int _nObjects; // The number of currently active objects
public:
CBagWield(CBofWindow *pParent = nullptr, const CBofRect &xRect = CBofRect());
virtual ~CBagWield();
static void initialize() {
_nWieldCursor = -1;
}
CBagObject *getCurrObj() const {
return _pCurrObj;
}
CBagObject *setCurrObj(CBagObject *pObj) {
return _pCurrObj = pObj;
}
static int getWieldCursor() {
return _nWieldCursor;
}
static void setWieldCursor(int n) {
_nWieldCursor = n;
}
ErrorCode update(CBofBitmap *pBmp, CBofPoint pt, CBofRect *pSrcRect = nullptr, int nMaskColor = -1) override;
ErrorCode loadFile(const CBofString &sFile) override;
bool onObjInteraction(CBagObject *pObj, CBagStorageDev *pSDev) override;
ErrorCode attach() override;
ErrorCode detach() override;
ErrorCode activateLocalObject(CBagObject *pObj) override;
ErrorCode deactivateLocalObject(CBagObject *pObj) override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,318 @@
/* 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/>.
*
*/
#include "bagel/spacebar/baglib/button_object.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/time_object.h"
#include "bagel/spacebar/baglib/rp_object.h"
#include "bagel/spacebar/baglib/wield.h"
#include "bagel/spacebar/baglib/zoom_pda.h"
namespace Bagel {
namespace SpaceBar {
#define ZOOM_MOO_WLD "MOOZ_WLD"
#define ZOOM_INV_WLD "INVZ_WLD"
#define ZOOM_MAP_WLD "MAPZ_WLD"
#define ZOOM_LOG_WLD "LOGZ_WLD"
// Keep track of updates...
static uint32 g_lZoomPDALastUpdate;
void SBZoomPda::initialize() {
g_lZoomPDALastUpdate = 0;
}
SBZoomPda::SBZoomPda(CBofWindow *pParent, const CBofRect &xRect, bool bActivated)
: CBagStorageDevWnd(),
SBBasePda(pParent, xRect, bActivated) {
_xSDevType = SDEV_ZOOMPDA;
}
ErrorCode SBZoomPda::onRender(CBofBitmap *pBmp, CBofRect *pRect) {
assert(isValidObject(this));
assert(pBmp != nullptr);
// Paint the storage device
if (pBmp != nullptr) {
bool bUpdate = false;
// Only clear the background and paint the backdrop if we've
// been instructed to.
if (preFilterPan()) {
preFilter(pBmp, pRect, (_curDisplay == nullptr ? nullptr : _curDisplay->getObjectList()));
// Paint our storage device the first time through and the next time
// through, this takes care of multiple text drawing problems (trust me!).
if (_bFirstPaint == false) {
setPreFilterPan(false);
}
if (getWorkBmp() != nullptr) {
getWorkBmp()->paint(pBmp, pRect, pRect);
}
bUpdate = true;
}
paintStorageDevice(nullptr, pBmp, pRect);
// Paint the inventory or Map to backdrop
if (bUpdate && (_curDisplay != nullptr))
_curDisplay->update(pBmp, _curDisplay->getPosition(), pRect);
}
return _errCode;
}
ErrorCode SBZoomPda::loadFile(const CBofString &sFile) {
ErrorCode errorCode = CBagStorageDev::loadFile(sFile);
removeObject(_mooWnd);
removeObject(_invWnd);
removeObject(_mapWnd);
removeObject(_logWnd);
return errorCode;
}
ErrorCode SBZoomPda::detach() {
bool bLogZoomed = (_logWnd == _curDisplay);
// Other classes need to know if we're zoomed
setZoomed(false);
if (_invWnd) {
_invWnd->detach();
_invWnd = nullptr;
}
if (_mooWnd) {
_mooWnd->detach();
_mooWnd = nullptr;
}
if (_mapWnd) {
_mapWnd->detach();
_mapWnd = nullptr;
}
if (_logWnd) {
_logWnd->detach();
_logWnd = nullptr;
}
// Since the regular PDA does not have a detach method (it doesn't get
// flushed out until you go to a flashback or quit the game), go through
// the entire list of RPO's (residue print objects) and restore the saved
// variable values. We do this so that any values that were changed in
// the zoomed version are propagated down to the un-zoomed pda.
CBagRPObject::synchronizeResiduePrintedObjects(bLogZoomed);
CBagStorageDevWnd::detach();
return ERR_NONE;
}
ErrorCode SBZoomPda::attach() {
// Other classes need to know if we're zoomed
setZoomed(true);
ErrorCode errorCode = CBagStorageDevWnd::attach();
if (errorCode == ERR_NONE) {
CBagStorageDev *pSDev;
if (!_mooWnd) {
pSDev = g_SDevManager->getStorageDevice(ZOOM_MOO_WLD);
if (pSDev != nullptr) {
_mooWnd = (CBagStorageDevBmp *)pSDev;
_mooWnd->setAssociateWnd(getAssociateWnd());
_mooWnd->setTransparent(false);
_mooWnd->setVisible(false);
errorCode = _mooWnd->attach();
}
} else {
// Already attached just update
_mooWnd->attachActiveObjects();
}
if (!_invWnd) {
pSDev = g_SDevManager->getStorageDevice(ZOOM_INV_WLD);
if (pSDev != nullptr) {
_invWnd = (CBagStorageDevBmp *)pSDev;
_invWnd->setAssociateWnd(getAssociateWnd());
_invWnd->setTransparent(false);
_invWnd->setVisible(false);
errorCode = _invWnd->attach();
} else {
bofMessageBox("No PDA INVENTORY found", __FILE__);
errorCode = ERR_UNKNOWN;
}
} else {
// Already attached just update
_invWnd->attachActiveObjects();
}
if (!_mapWnd) {
pSDev = g_SDevManager->getStorageDevice(ZOOM_MAP_WLD);
if (pSDev != nullptr) {
_mapWnd = (CBagStorageDevBmp *)pSDev;
_mapWnd->setAssociateWnd(getAssociateWnd());
_mapWnd->setTransparent(false);
_mapWnd->setVisible(false);
errorCode = _mapWnd->attach();
} else {
bofMessageBox("No PDA MAP found", __FILE__);
errorCode = ERR_UNKNOWN;
}
} else {
// Already attached just update
_mapWnd->attachActiveObjects();
}
if (!_logWnd) {
pSDev = g_SDevManager->getStorageDevice(ZOOM_LOG_WLD);
if (pSDev != nullptr) {
_logWnd = (CBagStorageDevBmp *)pSDev;
_logWnd->setAssociateWnd(getAssociateWnd());
_logWnd->setTransparent(false);
_logWnd->setVisible(false);
errorCode = _logWnd->attach();
}
} else {
// Already attached just update
_logWnd->attachActiveObjects();
}
if (_pdaMode == PDA_INV_MODE) {
showInventory();
} else if (_pdaMode == PDA_MAP_MODE) {
showMap();
} else if (_pdaMode == PDA_LOG_MODE) {
showLog();
}
show();
invalidateRect(nullptr);
updateWindow();
}
// Keep track of updates...
g_lZoomPDALastUpdate = 0;
return errorCode;
}
CBagObject *SBZoomPda::onNewButtonObject(const CBofString &) {
CBagButtonObject *PdaButtObj = new CBagButtonObject();
PdaButtObj->setCallBack(pdaButtonHandler, (SBBasePda *)this);
return PdaButtObj;
}
void SBZoomPda::onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void *) {
// Need to override the CBagStorageDevWnd::onLButtonUp(nFlags, xPoint)
// to do our own thing.
*_xCursorLocation = *xPoint;
CBofPoint xCursorLocation = devPtToViewPort(*xPoint);
CBagObject *pObj = getObject(xCursorLocation, true);
if (pObj != nullptr) {
if (pObj->isActive()) {
pObj->onLButtonUp(nFlags, xPoint);
setLActiveObject(pObj);
}
} else {
setLActivity(kMouseNONE);
if (_curDisplay) {
CBofRect offset = CBagStorageDev::getRect();
xPoint->x -= offset.topLeft().x;
xPoint->y -= offset.topLeft().y;
// Make sure this stuff is nice and dirty before calling off
// to the button handling routine, this assures that if we go from one screen
// to the next, then we'll get redrawn.
setPreFilterPan(true);
makeListDirty(_curDisplay->getObjectList());
_curDisplay->onLButtonUp(nFlags, xPoint, nullptr);
} else {
// We have no mode yet, then pass it to the default method
if (_pdaMode == PDA_NO_MODE) {
CBagStorageDevWnd::onLButtonUp(nFlags, xPoint);
}
}
}
// This thing could get trashed by the underlying code...
if (isCreated()) {
invalidateRect(nullptr);
updateWindow();
}
}
void SBZoomPda::onMouseMove(uint32 nFlags, CBofPoint *pPoint, void *) {
assert(isValidObject(this));
CBagStorageDev::onMouseMove(nFlags, pPoint, getAssociateWnd());
// This should be on update cursor virtual func
if (getExitOnEdge() && (pPoint->x < getExitOnEdge()) && (pPoint->y < 300) && !(getPrevSDev().isEmpty())) {
CBagMasterWin::setActiveCursor(10);
} else {
CBofRect cRect = getBackdrop()->getRect();
CBagMasterWin::setActiveCursor(getProperCursor(*pPoint, cRect));
}
}
void SBZoomPda::onMainLoop() {
uint32 nCurTime = getTimer();
// Force an update every 1/4 second
if (_pdaMode == PDA_INV_MODE || _pdaMode == PDA_MAP_MODE) {
if (nCurTime > (g_lZoomPDALastUpdate + 250)) {
g_lZoomPDALastUpdate = nCurTime;
setPreFilterPan(true);
}
}
CBagStorageDevWnd::onMainLoop();
}
ErrorCode SBZoomPda::attachActiveObjects() {
SBBasePda::attachActiveObjects();
return CBagStorageDevWnd::attachActiveObjects();
}
ErrorCode SBZoomPda::detachActiveObjects() {
SBBasePda::detachActiveObjects();
return CBagStorageDevWnd::detachActiveObjects();
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,67 @@
/* 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 BAGEL_BAGLIB_ZOOM_PDA_H
#define BAGEL_BAGLIB_ZOOM_PDA_H
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/baglib/base_pda.h"
namespace Bagel {
namespace SpaceBar {
class SBZoomPda : public CBagStorageDevWnd, public SBBasePda {
public:
/**
* Constructor
* @param pParent Pointer to the parent window
* @param xRect Pda in parent window
* @param bActivated State of PDA whe constructed (optional)
*/
SBZoomPda(CBofWindow *pParent = nullptr, const CBofRect &xRect = CBofRect(), bool bActivated = true);
static void initialize();
ErrorCode attach() override;
ErrorCode detach() override;
ErrorCode loadFile(const CBofString &sFile) override;
void onMouseMove(uint32 nFlags, CBofPoint *, void * = nullptr) override;
/**
* Called to overload specific types of sprite objects
* @retrn Pointer to the new object
*/
CBagObject *onNewButtonObject(const CBofString &sInit) override;
void onMainLoop() override;
void onLButtonUp(uint32 nFlags, CBofPoint *xPoint, void * = nullptr) override;
ErrorCode onRender(CBofBitmap *pBmp, CBofRect *pRect = nullptr) override;
ErrorCode attachActiveObjects() override;
ErrorCode detachActiveObjects() override;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,141 @@
/* 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/>.
*
*/
#include "bagel/spacebar/bib_odds_wnd.h"
#include "bagel/spacebar/bibble_window.h"
#include "bagel/spacebar/spacebar.h"
#include "bagel/spacebar/baglib/master_win.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/baglib/pan_window.h"
#include "bagel/spacebar/boflib/std_keys.h"
namespace Bagel {
namespace SpaceBar {
CBagObject *SBarBibOddsWnd::_wieldedObject;
void SBarBibOddsWnd::initialize() {
_wieldedObject = nullptr;
}
SBarBibOddsWnd::SBarBibOddsWnd() : CBagChatWnd() {
}
SBarBibOddsWnd::~SBarBibOddsWnd() {
}
ErrorCode SBarBibOddsWnd::detach() {
for (int i = 0; i < BIBBLE_NUM_BET_AREAS; i++) {
// The sprite object start in the script at 500
CBagObject *pObj = getObject(500 + i);
if (pObj != nullptr) {
int nPayIdx = pObj->getState();
g_engine->g_cBetAreas[i]._nPayOff1 = PAY_OFFS[nPayIdx]._nPay1;
g_engine->g_cBetAreas[i]._nPayOff2 = PAY_OFFS[nPayIdx]._nPay2;
}
}
if (_wieldedObject) {
g_SDevManager->addObject(CBagPanWindow::_pWieldBmp->getName(), _wieldedObject->getRefName());
_wieldedObject = nullptr;
}
return CBagChatWnd::detach();
}
void SBarBibOddsWnd::onKeyHit(uint32 lKey, uint32 lRepCount) {
CBagVar *pVar = g_VarManager->getVariable("TORSOSTATE");
if (pVar != nullptr) {
CBofString StateStr = pVar->getValue();
if (StateStr == "MAINMENU") {
switch (lKey) {
case BKEY_1:
pVar->setValue("VIDINFO");
attachActiveObjects();
break;
case BKEY_2:
pVar->setValue("SETBIBBLE");
attachActiveObjects();
break;
case BKEY_3:
pVar->setValue("BADCODE");
attachActiveObjects();
break;
case BKEY_4:
pVar->setValue("TIPS");
attachActiveObjects();
break;
case BKEY_5:
close();
break;
default:
break;
}
} else if (StateStr == "SETBIBBLE") {
switch (lKey) {
case BKEY_1:
pVar->setValue("SETBONK");
attachActiveObjects();
break;
case BKEY_2:
pVar->setValue("SETBAB");
attachActiveObjects();
break;
default:
break;
}
}
}
CBagChatWnd::onKeyHit(lKey, lRepCount);
}
void SBarBibOddsWnd::onMouseMove(uint32 nFlags, CBofPoint *pPoint, void *) {
CBagStorageDevWnd::onMouseMove(nFlags, pPoint);
}
ErrorCode SBarBibOddsWnd::attach() {
assert(isValidObject(this));
// If we have something wielded, put it on hold for now.
if (CBagPanWindow::_pWieldBmp != nullptr) {
_wieldedObject = CBagPanWindow::_pWieldBmp->getCurrObj();
if (_wieldedObject != nullptr) {
g_SDevManager->removeObject(CBagPanWindow::_pWieldBmp->getName(), _wieldedObject->getRefName());
}
}
// Don't call CBagChatWnd::attach() - We are overriding it's behavior
if (CBagStorageDevWnd::attach() == ERR_NONE) {
show();
invalidateRect(nullptr);
updateWindow();
}
return _errCode;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,51 @@
/* 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 BAGEL_SPACEBAR_BIB_ODDS_WND_H
#define BAGEL_SPACEBAR_BIB_ODDS_WND_H
#include "bagel/spacebar/baglib/chat_wnd.h"
namespace Bagel {
namespace SpaceBar {
#define NUM_PAYOFFS 16
class SBarBibOddsWnd : public CBagChatWnd {
public:
SBarBibOddsWnd();
virtual ~SBarBibOddsWnd();
virtual ErrorCode attach(); // Save wielded cursor
virtual ErrorCode detach(); // This function detaches the background and necessary bitmaps
void onMouseMove(uint32 nFlags, CBofPoint *xPoint, void * = nullptr);
void onKeyHit(uint32 lKey, uint32 lRepCount);
static void initialize();
static CBagObject *_wieldedObject;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
/* 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 BAGEL_SPACEBAR_BIBBLE_WINDOW_H
#define BAGEL_SPACEBAR_BIBBLE_WINDOW_H
#include "bagel/spacebar/baglib/storage_dev_win.h"
#include "bagel/spacebar/boflib/gui/text_box.h"
#include "bagel/spacebar/boflib/gui/button.h"
#include "bagel/spacebar/boflib/gfx/sprite.h"
#include "bagel/boflib/sound.h"
namespace Bagel {
namespace SpaceBar {
#define BIBBLE_NUM_BUTTONS 12
#define BIBBLE_NUM_BIBBLES 3
#define BIBBLE_NUM_SHOUTS 4
#define BIBBLE_NUM_PAYOFFS 16
#define BIBBLE_NUM_BET_AREAS 24
struct ST_PAYOFFS {
int _nPay1;
int _nPay2;
};
struct CBetAreaDef {
int _nBet;
int _left;
int _top;
int _right;
int _bottom;
int _nPayOff1;
int _nPayOff2;
const char *_cAudioFile;
const char *_cPayFile;
};
class CBetArea : public CBofObject {
public:
CBetArea() {}
CBetArea(const CBetAreaDef &def);
// Data members
CBofRect _cRect;
int _nBet = 0;
int _nPayOff1 = 0;
int _nPayOff2 = 0;
bool _bWon = false;
CBofString _cAudioFile;
CBofString _cPayFile;
};
extern CBetAreaDef BET_AREAS[BIBBLE_NUM_BET_AREAS];
extern const ST_PAYOFFS PAY_OFFS[BIBBLE_NUM_PAYOFFS];
class CBibbleWindow : public CBagStorageDevWnd {
public:
CBibbleWindow();
virtual ErrorCode attach();
virtual ErrorCode detach();
virtual void onBofButton(CBofObject *pButton, int nState);
virtual void onClose();
protected:
ErrorCode playGame();
ErrorCode bonkBibble(int nBibble, int nShout);
void calcOutcome();
ErrorCode displayCredits();
ErrorCode highlight(CBetArea *pArea, byte nColor);
ErrorCode unHighlight(CBetArea *pArea);
virtual void onLButtonDown(uint32 nFlags, CBofPoint *pPoint, void * = nullptr);
virtual void onLButtonUp(uint32 nFlags, CBofPoint *pPoint, void * = nullptr);
virtual void onLButtonDblClk(uint32 nFlags, CBofPoint *pPoint);
virtual void onKeyHit(uint32 lKey, uint32 lRepCount);
virtual void onPaint(CBofRect *pRect);
virtual void onMainLoop();
virtual void onTimer(uint32 /*nTimerID*/) {
// Do nothing
}
// Data
CBofSound *_pBkgSnd;
CBofBmpButton *_pButtons[BIBBLE_NUM_BUTTONS];
CBofText *_pCreditsText;
CBofSprite *_pMasterBibble;
CBofSprite *_pBibble[BIBBLE_NUM_BIBBLES];
CBofSprite *_pBall;
CBofSprite *_pArch1;
CBofSprite *_pArch2;
CBofSprite *_pArch3;
CBofSound *_pShouts[BIBBLE_NUM_SHOUTS];
uint32 _nNumCredits;
int _nBall1; // Which Bibble hit by ball 1
int _nBall2; // Which Bibble hit by ball 2
int _nBall3; // Which Bibble hit by ball 3
int _nBall1Said;
int _nBall2Said;
int _nBall3Said;
int _nNumShout1;
int _nNumShout2;
int _nNumShout3;
int _nNumShout4;
int _nNumTopBonks;
int _nNumMidBonks;
int _nNumBotBonks;
CBetArea *_pSelected;
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,252 @@
/* 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/>.
*
*/
#include "graphics/framelimiter.h"
#include "graphics/palette.h"
#include "graphics/paletteman.h"
#include "video/smk_decoder.h"
#include "bagel/spacebar/baglib/bagel.h"
#include "bagel/spacebar/boflib/debug.h"
#include "bagel/spacebar/boflib/app.h"
#include "bagel/spacebar/boflib/timer.h"
#include "bagel/spacebar/boflib/gfx/text.h"
#include "bagel/boflib/sound.h"
#include "bagel/bagel.h"
namespace Bagel {
namespace SpaceBar {
#define DEBUG_LOG "DEBUG.LOG"
#define DEBUG_INI "BOFFO.INI"
#define BOFDISP 0
CBofApp *CBofApp::_pBofApp;
CBofApp::CBofApp() {
StartupCode();
}
CBofApp::CBofApp(const char *pszAppName) {
StartupCode();
setAppName(pszAppName);
}
CBofApp::~CBofApp() {
ShutDownCode();
_szAppName[0] = '\0';
_pMainWnd = nullptr;
_pPalette = nullptr;
_pBofApp = nullptr;
}
void CBofApp::StartupCode() {
_pBofApp = this;
// Open the Boffo debug options file (BOFFO.INI)
g_pDebugOptions = new CBofDebugOptions(DEBUG_INI);
g_pDebugOptions->readSetting("DebugOptions", "MainLoops", &_nIterations, DEFAULT_MAINLOOPS);
//
// Initialize the boffo libraries
//
// Init the Window library
CBofWindow::initialize();
// Init the text library
CBofText::initialize();
}
void CBofApp::ShutDownCode() {
// Un-initialize the text library
CBofText::shutdown();
// Shut down the Window library
CBofWindow::shutdown();
// Kill any shared palette
CBofPalette::setSharedPalette(nullptr);
if (g_pDebugOptions != nullptr) {
delete g_pDebugOptions;
g_pDebugOptions = nullptr;
}
}
ErrorCode CBofApp::preInit() {
if ((_pPalette == nullptr) && (_pDefPalette == nullptr)) {
_pDefPalette = new CBofPalette();
_pDefPalette->createDefault();
setPalette(_pDefPalette);
}
return _errCode;
}
ErrorCode CBofApp::initialize() {
return _errCode;
}
ErrorCode CBofApp::runApp() {
int nCount = _nIterations;
// Acquire and dispatch messages until we need to quit, or too many errors
Graphics::FrameLimiter limiter(g_system, 60, false);
while (!g_engine->shouldQuit() && CBofError::getErrorCount() < MAX_ERRORS) {
// Support for playing videos via the console
if (_consoleVideo && _consoleVideo->isPlaying()) {
if (_consoleVideo->needsUpdate()) {
const Graphics::Surface *s = _consoleVideo->decodeNextFrame();
Graphics::Palette pal(_consoleVideo->getPalette(), 256);
g_engine->getScreen()->blitFrom(*s, Common::Point(0, 0), &pal);
}
limiter.delayBeforeSwap();
g_engine->getScreen()->update();
limiter.startFrame();
continue;
}
delete _consoleVideo;
_consoleVideo = nullptr;
// Handle sounds and timers
CBofSound::audioTask();
CBofTimer::handleTimers();
if (nCount < 0) {
nCount++;
if (nCount == 0)
nCount = 1;
} else {
for (int i = 0; i < nCount; i++) {
// Give each window it's own main loop (sort-of)
CBofWindow *pWindow = CBofWindow::getWindowList();
while (pWindow != nullptr) {
if (shouldQuit())
return ERR_NONE;
if (pWindow->isCreated()) {
pWindow->onMainLoop();
}
pWindow = (CBofWindow *)pWindow->getNext();
}
}
nCount = _nIterations;
}
// Handle events
_pMainWnd->handleEvents();
limiter.delayBeforeSwap();
g_engine->getScreen()->update();
limiter.startFrame();
}
return _errCode;
}
ErrorCode CBofApp::shutdown() {
return _errCode;
}
void CBofApp::postShutDown() {
delete _pWindow;
_pWindow = nullptr;
// No more palettes
_pPalette = nullptr;
delete _pDefPalette;
_pDefPalette = nullptr;
}
void CBofApp::setPalette(CBofPalette *pPalette) {
_pPalette = pPalette;
if (pPalette != nullptr) {
if (g_system->getScreenFormat().bytesPerPixel == 1) {
const auto &pal = pPalette->getPalette();
g_system->getPaletteManager()->setPalette(pal._data, 0, pal._numColors);
}
} else {
// Use default palette
_pPalette = _pDefPalette;
}
}
void CBofApp::addCursor(CBofCursor &cCursor) {
_cCursorList.addToTail(cCursor);
}
void CBofApp::delCursor(int nIndex) {
_cCursorList.remove(nIndex);
}
bool CBofApp::consolePlayVideo(const Common::Path &path) {
delete _consoleVideo;
_consoleVideo = new Video::SmackerDecoder();
_consoleVideo->setSoundType(Audio::Mixer::kSFXSoundType);
if (_consoleVideo->loadFile(path)) {
_consoleVideo->start();
return true;
} else {
delete _consoleVideo;
_consoleVideo = nullptr;
return false;
}
}
///////////////////////////////////////////////////////////////////////////
// Global routines
///////////////////////////////////////////////////////////////////////////
CBofPoint getMousePos() {
return CBofWindow::getMousePos();
}
void bofMessageBox(const char *pszTitle, const char *pszMessage) {
Common::String msg = Common::String::format("%s - %s", pszTitle, pszMessage);
g_engine->errorDialog(msg.c_str());
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,165 @@
/* 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 BAGEL_BOFLIB_APP_H
#define BAGEL_BOFLIB_APP_H
#include "video/video_decoder.h"
#include "bagel/spacebar/boflib/gui/window.h"
#include "bagel/spacebar/boflib/gfx/cursor.h"
#include "bagel/boflib/error.h"
#include "bagel/spacebar/boflib/list.h"
namespace Bagel {
namespace SpaceBar {
#define MAX_APP_NAME 128
#define DEFAULT_MAINLOOPS 1
#define kReallyFastPPC 50
#define kReallySlowPPC 200
class CBofApp : public CBofError {
private:
CBofWindow *_pWindow = nullptr;
CBofWindow *_captureControl = nullptr;
CBofWindow *_focusControl = nullptr;
Video::VideoDecoder *_consoleVideo = nullptr;
protected:
void StartupCode();
void ShutDownCode();
char _szAppName[MAX_APP_NAME] = { 0 };
CBofList<CBofCursor> _cCursorList;
CBofCursor _cDefaultCursor;
CBofWindow *_pMainWnd = nullptr;
CBofPalette *_pPalette = nullptr;
CBofPalette *_pDefPalette = nullptr;
int _nScreenDX = 0;
int _nScreenDY = 0;
int _nColorDepth = 0;
int _nIterations = DEFAULT_MAINLOOPS;
static CBofApp *_pBofApp;
virtual bool shouldQuit() const = 0;
public:
CBofApp();
CBofApp(const char *pszAppName);
virtual ~CBofApp();
ErrorCode preInit();
void postShutDown();
// These functions can be overridden by the child class
virtual ErrorCode initialize();
virtual ErrorCode runApp();
virtual ErrorCode shutdown();
virtual void setAppName(const char *pszNewAppName) {
Common::strcpy_s(_szAppName, pszNewAppName);
}
const char *getAppName() const {
return (const char *)_szAppName;
}
void setMainWindow(CBofWindow *pWnd) {
_pMainWnd = pWnd;
}
CBofWindow *getMainWindow() const {
return _pMainWnd;
}
CBofWindow *getActualWindow() const {
return _pWindow;
}
void setPalette(CBofPalette *pPalette);
CBofPalette *getPalette() const {
return _pPalette;
}
int screenWidth() const {
return _nScreenDX;
}
int screenHeight() const {
return _nScreenDY;
}
int screenDepth() const {
return _nColorDepth;
}
CBofCursor getDefaultCursor() const {
return _cDefaultCursor;
}
void setDefaultCursor(CBofCursor &cCursor) {
_cDefaultCursor = cCursor;
}
void addCursor(CBofCursor &cCursor);
void delCursor(int nIndex);
CBofCursor getCursor(int nIndex) {
return _cCursorList[nIndex];
}
int getNumberOfCursors() const {
return _cCursorList.getCount();
}
void setCaptureControl(CBofWindow *ctl) {
_captureControl = ctl;
}
CBofWindow *getCaptureControl() const {
return _captureControl;
}
void setFocusControl(CBofWindow *ctl) {
_focusControl = ctl;
}
CBofWindow *getFocusControl() const {
return _focusControl;
}
bool consolePlayVideo(const Common::Path &path);
static uint32 getMachineSpeed() {
return kReallyFastPPC;
}
static CBofApp *getApp() {
return _pBofApp;
}
};
// Global routines
//
void bofMessageBox(const char *pszTitle, const char *pszMessage);
CBofPoint getMousePos();
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,57 @@
/* 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 BAGEL_BOFLIB_ARRAY_H
#define BAGEL_BOFLIB_ARRAY_H
#include "common/array.h"
namespace Bagel {
namespace SpaceBar {
template<class T>
class Array : public Common::Array<T> {
public:
int indexOf(T t) {
for (int i = 0; i < (int)this->size(); ++i) {
if (this->operator[](i) == t)
return i;
}
return -1;
}
bool contains(T t) const {
return this->indexOf(t) != -1;
}
void remove(T t) {
int idx = this->indexOf(t);
if (idx != -1)
this->remove_at(idx);
}
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,132 @@
/* 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/>.
*
*/
#include "bagel/spacebar/boflib/crc.h"
namespace Bagel {
namespace SpaceBar {
static const uint16 crc32tabLo[256] = {
0x0000, 0x3096, 0x612c, 0x51ba, 0xc419, 0xf48f, 0xa535, 0x95a3,
0x8832, 0xb8a4, 0xe91e, 0xd988, 0x4c2b, 0x7cbd, 0x2d07, 0x1d91,
0x1064, 0x20f2, 0x7148, 0x41de, 0xd47d, 0xe4eb, 0xb551, 0x85c7,
0x9856, 0xa8c0, 0xf97a, 0xc9ec, 0x5c4f, 0x6cd9, 0x3d63, 0x0df5,
0x20c8, 0x105e, 0x41e4, 0x7172, 0xe4d1, 0xd447, 0x85fd, 0xb56b,
0xa8fa, 0x986c, 0xc9d6, 0xf940, 0x6ce3, 0x5c75, 0x0dcf, 0x3d59,
0x30ac, 0x003a, 0x5180, 0x6116, 0xf4b5, 0xc423, 0x9599, 0xa50f,
0xb89e, 0x8808, 0xd9b2, 0xe924, 0x7c87, 0x4c11, 0x1dab, 0x2d3d,
0x4190, 0x7106, 0x20bc, 0x102a, 0x8589, 0xb51f, 0xe4a5, 0xd433,
0xc9a2, 0xf934, 0xa88e, 0x9818, 0x0dbb, 0x3d2d, 0x6c97, 0x5c01,
0x51f4, 0x6162, 0x30d8, 0x004e, 0x95ed, 0xa57b, 0xf4c1, 0xc457,
0xd9c6, 0xe950, 0xb8ea, 0x887c, 0x1ddf, 0x2d49, 0x7cf3, 0x4c65,
0x6158, 0x51ce, 0x0074, 0x30e2, 0xa541, 0x95d7, 0xc46d, 0xf4fb,
0xe96a, 0xd9fc, 0x8846, 0xb8d0, 0x2d73, 0x1de5, 0x4c5f, 0x7cc9,
0x713c, 0x41aa, 0x1010, 0x2086, 0xb525, 0x85b3, 0xd409, 0xe49f,
0xf90e, 0xc998, 0x9822, 0xa8b4, 0x3d17, 0x0d81, 0x5c3b, 0x6cad,
0x8320, 0xb3b6, 0xe20c, 0xd29a, 0x4739, 0x77af, 0x2615, 0x1683,
0x0b12, 0x3b84, 0x6a3e, 0x5aa8, 0xcf0b, 0xff9d, 0xae27, 0x9eb1,
0x9344, 0xa3d2, 0xf268, 0xc2fe, 0x575d, 0x67cb, 0x3671, 0x06e7,
0x1b76, 0x2be0, 0x7a5a, 0x4acc, 0xdf6f, 0xeff9, 0xbe43, 0x8ed5,
0xa3e8, 0x937e, 0xc2c4, 0xf252, 0x67f1, 0x5767, 0x06dd, 0x364b,
0x2bda, 0x1b4c, 0x4af6, 0x7a60, 0xefc3, 0xdf55, 0x8eef, 0xbe79,
0xb38c, 0x831a, 0xd2a0, 0xe236, 0x7795, 0x4703, 0x16b9, 0x262f,
0x3bbe, 0x0b28, 0x5a92, 0x6a04, 0xffa7, 0xcf31, 0x9e8b, 0xae1d,
0xc2b0, 0xf226, 0xa39c, 0x930a, 0x06a9, 0x363f, 0x6785, 0x5713,
0x4a82, 0x7a14, 0x2bae, 0x1b38, 0x8e9b, 0xbe0d, 0xefb7, 0xdf21,
0xd2d4, 0xe242, 0xb3f8, 0x836e, 0x16cd, 0x265b, 0x77e1, 0x4777,
0x5ae6, 0x6a70, 0x3bca, 0x0b5c, 0x9eff, 0xae69, 0xffd3, 0xcf45,
0xe278, 0xd2ee, 0x8354, 0xb3c2, 0x2661, 0x16f7, 0x474d, 0x77db,
0x6a4a, 0x5adc, 0x0b66, 0x3bf0, 0xae53, 0x9ec5, 0xcf7f, 0xffe9,
0xf21c, 0xc28a, 0x9330, 0xa3a6, 0x3605, 0x0693, 0x5729, 0x67bf,
0x7a2e, 0x4ab8, 0x1b02, 0x2b94, 0xbe37, 0x8ea1, 0xdf1b, 0xef8d
};
static const uint16 crc32tabHi[256] = {
0x0000, 0x7707, 0xee0e, 0x9909, 0x076d, 0x706a, 0xe963, 0x9e64,
0x0edb, 0x79dc, 0xe0d5, 0x97d2, 0x09b6, 0x7eb1, 0xe7b8, 0x90bf,
0x1db7, 0x6ab0, 0xf3b9, 0x84be, 0x1ada, 0x6ddd, 0xf4d4, 0x83d3,
0x136c, 0x646b, 0xfd62, 0x8a65, 0x1401, 0x6306, 0xfa0f, 0x8d08,
0x3b6e, 0x4c69, 0xd560, 0xa267, 0x3c03, 0x4b04, 0xd20d, 0xa50a,
0x35b5, 0x42b2, 0xdbbb, 0xacbc, 0x32d8, 0x45df, 0xdcd6, 0xabd1,
0x26d9, 0x51de, 0xc8d7, 0xbfd0, 0x21b4, 0x56b3, 0xcfba, 0xb8bd,
0x2802, 0x5f05, 0xc60c, 0xb10b, 0x2f6f, 0x5868, 0xc161, 0xb666,
0x76dc, 0x01db, 0x98d2, 0xefd5, 0x71b1, 0x06b6, 0x9fbf, 0xe8b8,
0x7807, 0x0f00, 0x9609, 0xe10e, 0x7f6a, 0x086d, 0x9164, 0xe663,
0x6b6b, 0x1c6c, 0x8565, 0xf262, 0x6c06, 0x1b01, 0x8208, 0xf50f,
0x65b0, 0x12b7, 0x8bbe, 0xfcb9, 0x62dd, 0x15da, 0x8cd3, 0xfbd4,
0x4db2, 0x3ab5, 0xa3bc, 0xd4bb, 0x4adf, 0x3dd8, 0xa4d1, 0xd3d6,
0x4369, 0x346e, 0xad67, 0xda60, 0x4404, 0x3303, 0xaa0a, 0xdd0d,
0x5005, 0x2702, 0xbe0b, 0xc90c, 0x5768, 0x206f, 0xb966, 0xce61,
0x5ede, 0x29d9, 0xb0d0, 0xc7d7, 0x59b3, 0x2eb4, 0xb7bd, 0xc0ba,
0xedb8, 0x9abf, 0x03b6, 0x74b1, 0xead5, 0x9dd2, 0x04db, 0x73dc,
0xe363, 0x9464, 0x0d6d, 0x7a6a, 0xe40e, 0x9309, 0x0a00, 0x7d07,
0xf00f, 0x8708, 0x1e01, 0x6906, 0xf762, 0x8065, 0x196c, 0x6e6b,
0xfed4, 0x89d3, 0x10da, 0x67dd, 0xf9b9, 0x8ebe, 0x17b7, 0x60b0,
0xd6d6, 0xa1d1, 0x38d8, 0x4fdf, 0xd1bb, 0xa6bc, 0x3fb5, 0x48b2,
0xd80d, 0xaf0a, 0x3603, 0x4104, 0xdf60, 0xa867, 0x316e, 0x4669,
0xcb61, 0xbc66, 0x256f, 0x5268, 0xcc0c, 0xbb0b, 0x2202, 0x5505,
0xc5ba, 0xb2bd, 0x2bb4, 0x5cb3, 0xc2d7, 0xb5d0, 0x2cd9, 0x5bde,
0x9b64, 0xec63, 0x756a, 0x026d, 0x9c09, 0xeb0e, 0x7207, 0x0500,
0x95bf, 0xe2b8, 0x7bb1, 0x0cb6, 0x92d2, 0xe5d5, 0x7cdc, 0x0bdb,
0x86d3, 0xf1d4, 0x68dd, 0x1fda, 0x81be, 0xf6b9, 0x6fb0, 0x18b7,
0x8808, 0xff0f, 0x6606, 0x1101, 0x8f65, 0xf862, 0x616b, 0x166c,
0xa00a, 0xd70d, 0x4e04, 0x3903, 0xa767, 0xd060, 0x4969, 0x3e6e,
0xaed1, 0xd9d6, 0x40df, 0x37d8, 0xa9bc, 0xdebb, 0x47b2, 0x30b5,
0xbdbd, 0xcaba, 0x53b3, 0x24b4, 0xbad0, 0xcdd7, 0x54de, 0x23d9,
0xb366, 0xc461, 0x5d68, 0x2a6f, 0xb40b, 0xc30c, 0x5a05, 0x2d02
};
uint32 calculateCRC(const void *pBuffer, int32 lBufLen, uint32 lCrcValue) {
assert(pBuffer != nullptr);
assert(lBufLen > 0);
const byte *p = (const byte *)pBuffer;
int32 i = -1;
while (++i < lBufLen) {
byte c = (byte)(*p ^ (byte)lCrcValue);
lCrcValue = (lCrcValue >> 8) ^ crc32tabLo[c] ^ ((uint32)crc32tabHi[c] << 16);
p++;
}
return lCrcValue;
}
uint32 calculateCRC(const int32 *pBuffer, int32 lBufLen, uint32 lCrcValue) {
assert(pBuffer != nullptr);
assert(lBufLen > 0);
const int32 *p = pBuffer;
for (int i = 0; i < lBufLen; ++i) {
uint32 val = *(const uint32 *)p++;
for (int j = 0; j < 4; ++j, val >>= 8) {
byte c = (byte)((val & 0xff) ^ (byte)lCrcValue);
lCrcValue = (lCrcValue >> 8) ^ crc32tabLo[c] ^ ((uint32)crc32tabHi[c] << 16);
}
}
return lCrcValue;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,44 @@
/* 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 BAGEL_BOFLIB_CRC_H
#define BAGEL_BOFLIB_CRC_H
#include "bagel/boflib/stdinc.h"
namespace Bagel {
namespace SpaceBar {
/**
* Calculates the CRC (Cyclic Redundancy Check) for a buffer
* @param pBuffer Pointer to buffer
* @param lBufLen Length of this buffer
* @param lCrcValue Previous CRC value (if running CRC)
* @return New CRC value
*/
extern uint32 calculateCRC(const void *pBuffer, int32 lBufLen, uint32 lCrcValue = 0);
extern uint32 calculateCRC(const int32 *pBuffer, int32 lBufLen, uint32 lCrcValue = 0);
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,820 @@
/* 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/>.
*
*/
#include "bagel/spacebar/boflib/dat_file.h"
#include "bagel/spacebar/boflib/crc.h"
#include "bagel/spacebar/boflib/debug.h"
#include "bagel/boflib/log.h"
#include "bagel/boflib/misc.h"
#include "bagel/boflib/stdinc.h"
#include "bagel/boflib/file_functions.h"
namespace Bagel {
namespace SpaceBar {
// Local prototypes
static uint32 CreateHashCode(const byte *);
void HeaderRec::synchronize(Common::Serializer &s) {
s.syncAsSint32LE(_lOffset);
s.syncAsSint32LE(_lLength);
s.syncAsUint32LE(_lCrc);
s.syncAsUint32LE(_lKey);
}
void HeadInfo::synchronize(Common::Serializer &s) {
s.syncAsSint32LE(_lNumRecs);
s.syncAsSint32LE(_lAddress);
s.syncAsUint32LE(_lFlags);
s.syncAsUint32LE(_lFootCrc);
}
CBofDataFile::CBofDataFile() {
_szFileName[0] = '\0';
_szPassWord[0] = '\0';
_lHeaderLength = 0;
_lNumRecs = 0;
_pHeader = nullptr;
_bHeaderDirty = false;
}
ErrorCode CBofDataFile::setFile(const char *pszFileName, uint32 lFlags) {
assert(isValidObject(this));
// Validate input
assert(pszFileName != nullptr);
assert(strlen(pszFileName) < MAX_FNAME);
// Release any previous data-file
releaseFile();
// All data files are binary, so force it
lFlags |= CBF_BINARY;
// Remember the flags
_lFlags = lFlags;
if (fileGetFullPath(_szFileName, pszFileName) != nullptr) {
if (open() == ERR_NONE) {
// Read header block
readHeader();
// Close data file if we are not keeping it open
if (!(_lFlags & CDF_KEEPOPEN)) {
close();
}
} else
reportError(ERR_FOPEN, "Could not open file %s", _szFileName);
} else {
reportError(ERR_FFIND, "Could not build full path to %s", pszFileName);
}
return _errCode;
}
CBofDataFile::~CBofDataFile() {
assert(isValidObject(this));
releaseFile();
}
ErrorCode CBofDataFile::releaseFile() {
assert(isValidObject(this));
// If header was modified
if (_bHeaderDirty) {
// Write header to disk
writeHeader();
}
close();
// Free header buffer
delete[] _pHeader;
_pHeader = nullptr;
return _errCode;
}
ErrorCode CBofDataFile::create() {
assert(isValidObject(this));
HeadInfo stHeaderInfo;
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
if (_stream != nullptr) {
close();
}
// Re-initialize
delete[] _pHeader;
_pHeader = nullptr;
_stream = nullptr;
_lHeaderLength = 0;
_bHeaderDirty = false;
stHeaderInfo._lNumRecs = _lNumRecs = 0;
stHeaderInfo._lAddress = HeadInfo::size();
// Create the file
if (CBofFile::create(_szFileName, _lFlags) == ERR_NONE) {
// Write empty header info
if (write(stHeaderInfo) != ERR_NONE) {
_errCode = ERR_FWRITE;
}
seek(0);
} else {
_errCode = ERR_FOPEN;
}
}
return _errCode;
}
ErrorCode CBofDataFile::open() {
assert(isValidObject(this));
// Only continue if there is no current error
if (_errCode == ERR_NONE && _stream == nullptr) {
if (!(_lFlags & CDF_READONLY)) {
if (_lFlags & CDF_SAVEFILE) {
if (_lFlags & CDF_CREATE)
create();
} else if (!fileExists(_szFileName))
create();
}
if (_stream == nullptr) {
// Open data file
CBofFile::open(_szFileName, _lFlags);
}
}
return _errCode;
}
ErrorCode CBofDataFile::close() {
assert(isValidObject(this));
if (_stream != nullptr) {
if (_bHeaderDirty) {
writeHeader();
}
CBofFile::close();
}
return _errCode;
}
ErrorCode CBofDataFile::readHeader() {
assert(isValidObject(this));
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
if (_stream == nullptr) {
open();
}
if (!errorOccurred()) {
// Determine number of records in file
HeadInfo stHeaderInfo;
if (read(stHeaderInfo) == ERR_NONE) {
_lNumRecs = stHeaderInfo._lNumRecs;
_lHeaderStart = stHeaderInfo._lAddress;
// Length of header is number of records * header-record size
_lHeaderLength = _lNumRecs * HeaderRec::size();
Common::SeekableReadStream *rs = dynamic_cast<Common::SeekableReadStream *>(_stream);
assert(rs);
int32 lfileLength = rs->size();
// Make sure header contains valid info
if ((_lHeaderStart >= HeadInfo::size()) &&
(_lHeaderStart <= lfileLength) && (_lHeaderLength >= 0) &&
(_lHeaderLength < lfileLength)) {
// Force Encrypted, and Compress if existing file has them
_lFlags |= stHeaderInfo._lFlags & CDF_ENCRYPT;
_lFlags |= stHeaderInfo._lFlags & CDF_COMPRESSED;
if (_lHeaderLength != 0) {
// Allocate buffer to hold header
_pHeader = new HeaderRec[(int)_lNumRecs];
// Seek to start of header
seek(_lHeaderStart);
// Read header
ErrorCode errorCode = ERR_NONE;
for (int i = 0; i < _lNumRecs && errorCode == ERR_NONE; ++i) {
errorCode = read(_pHeader[i]);
}
if (errorCode == ERR_NONE) {
uint32 lCrc = calculateCRC(&_pHeader->_lOffset, 4 * _lNumRecs);
if (lCrc != stHeaderInfo._lFootCrc) {
logError(buildString("Error: '%s' has invalid footer", _szFileName));
_errCode = ERR_CRC;
}
} else {
logError(buildString("Error: Could not read footer in file '%s'", _szFileName));
_errCode = ERR_FREAD;
}
}
} else {
logError(buildString("Error: '%s' has invalid header", _szFileName));
_errCode = ERR_FTYPE;
}
} else {
logError(buildString("Error: Could not read header in file '%s'", _szFileName));
_errCode = ERR_FREAD;
}
}
}
return _errCode;
}
ErrorCode CBofDataFile::writeHeader() {
assert(isValidObject(this));
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Open the data file if it's not already open
if (_stream == nullptr) {
open();
}
if (_errCode == ERR_NONE) {
// Header starts at the end of the last record
HeaderRec *pRec = &_pHeader[_lNumRecs - 1];
_lHeaderStart = pRec->_lOffset + pRec->_lLength;
HeadInfo stHeaderInfo;
stHeaderInfo._lNumRecs = _lNumRecs;
stHeaderInfo._lAddress = _lHeaderStart;
stHeaderInfo._lFlags = _lFlags;
stHeaderInfo._lFootCrc = calculateCRC(&_pHeader->_lOffset, 4 * _lNumRecs);
// Seek to front of file to write header info
seekToBeginning();
if (write(stHeaderInfo) == ERR_NONE) {
// Seek to start of where header is to be written
seek(_lHeaderStart);
// Write header to data file
ErrorCode errorCode = ERR_NONE;
for (int i = 0; i < _lNumRecs && errorCode == ERR_NONE; ++i) {
errorCode = write(_pHeader[i]);
}
if (errorCode == ERR_NONE) {
// Header is now clean
_bHeaderDirty = false;
} else {
logError(buildString("Error writing footer to file '%s'", _szFileName));
_errCode = ERR_FWRITE;
}
} else {
logError(buildString("Error writing header to file '%s'", _szFileName));
_errCode = ERR_FWRITE;
}
}
}
return _errCode;
}
ErrorCode CBofDataFile::readRecord(int32 lRecNum, void *pBuf) {
assert(isValidObject(this));
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Can't write to nullptr pointers
assert(pBuf != nullptr);
// Validate record number
assert(lRecNum >= 0 && lRecNum < _lNumRecs);
// Make sure we have a valid header
assert(_pHeader != nullptr);
// Get info about address of where record starts
// and how large the record is.
HeaderRec *pRecInfo = &_pHeader[(int)lRecNum];
// Open the data file if it's not already open
if (_stream == nullptr) {
open();
}
if (_errCode == ERR_NONE) {
// Seek to that point in the file
seek(pRecInfo->_lOffset);
// Read in the record
if (read(pBuf, pRecInfo->_lLength) == ERR_NONE) {
// If this file is encrypted, then decrypt it
if (_lFlags & CDF_ENCRYPT) {
decrypt(pBuf, (int)pRecInfo->_lLength, _szPassWord);
}
// Calculate and verify this record's CRC value
uint32 lCrc = calculateCRC(pBuf, (int)pRecInfo->_lLength);
if (lCrc != pRecInfo->_lCrc) {
_errCode = ERR_CRC;
}
} else {
logError(buildString("Error reading record %d in file '%s'", lRecNum, _szFileName));
_errCode = ERR_FREAD;
}
}
}
return _errCode;
}
ErrorCode CBofDataFile::readFromFile(int32 lRecNum, void *pBuf, int32 lBytes) {
assert(isValidObject(this));
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Can't write to nullptr pointers
assert(pBuf != nullptr);
// Validate record number
assert(lRecNum >= 0 && lRecNum < _lNumRecs);
// Make sure we have a valid header
assert(_pHeader != nullptr);
// Get info about address of where record starts
// and how large the record is.
HeaderRec *pRecInfo = &_pHeader[(int)lRecNum];
// Open the data file if it's not already open
if (_stream == nullptr) {
open();
}
if (_errCode == ERR_NONE) {
// Seek to that point in the file
seek(pRecInfo->_lOffset);
// Read in the requested bytes...
if (read(pBuf, lBytes) == ERR_NONE) {
// If this file is encrypted, then decrypt it
if (_lFlags & CDF_ENCRYPT) {
decryptPartial(pBuf, (int32)pRecInfo->_lLength, (int32)lBytes, _szPassWord);
}
// Don't bother with a CRC as this chunk of input won't generate a proper
// CRC anyway.
} else {
logError(buildString("Error reading record %u in file '%s'", lRecNum, _szFileName));
_errCode = ERR_FREAD;
}
}
}
return _errCode;
}
ErrorCode CBofDataFile::writeRecord(int32 lRecNum, void *pBuf, int32 lSize, bool bUpdateHeader, uint32 lKey) {
assert(isValidObject(this));
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Validate record number
assert(lRecNum >= 0 && lRecNum < _lNumRecs);
// Validate input buffer
assert(pBuf != nullptr);
// There must already be a valid header
assert(_pHeader != nullptr);
if (lSize == -1)
lSize = _pHeader[(int)lRecNum]._lLength;
int32 lPrevOffset = HeadInfo::size();
int32 lPrevLength = 0;
if (lRecNum != 0) {
lPrevOffset = _pHeader[(int)lRecNum - 1]._lOffset;
lPrevLength = _pHeader[(int)lRecNum - 1]._lLength;
}
HeaderRec *pRecInfo = &_pHeader[(int)lRecNum];
// Header needs to updated
_bHeaderDirty = true;
if (_stream == nullptr) {
open();
}
// This record starts at the end of the last record
pRecInfo->_lOffset = lPrevOffset + lPrevLength;
// Seek to where we want to write this record
seek(pRecInfo->_lOffset);
// Calculate new hash code based on this records key
pRecInfo->_lKey = lKey;
if (lKey == 0xFFFFFFFF) {
pRecInfo->_lKey = CreateHashCode((const byte *)pBuf);
}
// Calculate this record's CRC value
pRecInfo->_lCrc = calculateCRC(pBuf, lSize);
if (_lFlags & CDF_ENCRYPT) {
encrypt(pBuf, lSize, _szPassWord);
}
// If new record is larger then original
if (lSize > pRecInfo->_lLength) {
// How many bytes back do we have to write?
int32 lDiff = lSize - pRecInfo->_lLength;
//
// Move the rest of file back that many bytes
//
// Read the rest of the file in chunks (of 200k or less),
// and write each chunk back in it's new position.
//
int32 lBufLength = getLength() - (pRecInfo->_lOffset + pRecInfo->_lLength);
int32 lChunkSize = MIN(lBufLength, (int32)200000);
// Allocate a buffer big enough for one chunk
byte *pTmpBuf = (byte *)bofAlloc(lChunkSize);
// While there is data to move
while (lBufLength > 0) {
// Seek to beginning of the source for this chunk
setPosition(pRecInfo->_lOffset + pRecInfo->_lLength + lBufLength - lChunkSize);
// Read the chunk
read(pTmpBuf, lChunkSize);
// Seek to this chunks new position (offset by 'lDiff' bytes)
setPosition(pRecInfo->_lOffset + pRecInfo->_lLength + lBufLength - lChunkSize + lDiff);
// Write chunk to new position
write(pTmpBuf, lChunkSize);
// That much less to do next time through
lBufLength -= lChunkSize;
// Last chunk is lBufLength
lChunkSize = MIN(lBufLength, lChunkSize);
}
// Don't need that temp buffer anymore
bofFree(pTmpBuf);
// Tell the rest of the records that they moved
for (int i = lRecNum + 1; i < getNumberOfRecs(); i++) {
_pHeader[i]._lOffset += lDiff;
}
// Remember it's new length
pRecInfo->_lLength = lSize;
// Seek to where we want to write this record
seek(pRecInfo->_lOffset);
// Write this record
write(pBuf, lSize);
// If we are to update the header now
if (bUpdateHeader) {
writeHeader();
}
} else {
// Write this record
if (write(pBuf, lSize) == ERR_NONE) {
// If this record got smaller
if (pRecInfo->_lLength > lSize) {
// Remember it's length
pRecInfo->_lLength = lSize;
int bufferSize = getMaxRecSize();
if (bufferSize <= 0)
fatalError(ERR_FREAD, "Invalid size read in header data");
// Allocate a buffer that could hold the largest record
byte *pTmpBuf = (byte *)bofAlloc(bufferSize);
for (int i = (int)lRecNum + 1; i < (int)_lNumRecs - 1; i++) {
_errCode = readRecord(i, pTmpBuf);
if (_errCode != ERR_NONE)
break;
_errCode = writeRecord(i + 1, pTmpBuf);
if (_errCode != ERR_NONE)
break;
}
bofFree(pTmpBuf);
}
// If we are to update the header now
if (bUpdateHeader) {
writeHeader();
}
} else {
_errCode = ERR_FWRITE;
}
}
// If this record is encrypted the decrypt it
if (_lFlags & CDF_ENCRYPT) {
decrypt(pBuf, (int)pRecInfo->_lLength, _szPassWord);
}
}
return _errCode;
}
ErrorCode CBofDataFile::verifyRecord(int32 lRecNum) {
assert(isValidObject(this));
if (_errCode == ERR_NONE) {
// Validate record number
assert(lRecNum >= 0 && lRecNum < _lNumRecs);
// Allocate space to hold this record
void *pBuf = bofAlloc((int)getRecSize(lRecNum));
_errCode = readRecord(lRecNum, pBuf);
bofFree(pBuf);
}
return _errCode;
}
ErrorCode CBofDataFile::verifyAllRecords() {
assert(isValidObject(this));
if (_errCode == ERR_NONE) {
int32 n = getNumberOfRecs();
for (int32 i = 0; i < n; i++) {
_errCode = verifyRecord(i);
if (_errCode != ERR_NONE) {
break;
}
}
}
return _errCode;
}
ErrorCode CBofDataFile::addRecord(void *pBuf, int32 lLength, bool bUpdateHeader, uint32 lKey) {
assert(isValidObject(this));
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Validate input
assert(pBuf != nullptr);
assert(lLength > 0);
if (lLength > 0) {
if (_stream == nullptr) {
open();
}
if (_errCode == ERR_NONE) {
_lNumRecs++;
HeaderRec *pTmpHeader = new HeaderRec[(int)_lNumRecs];
for (int i = 0; i < _lNumRecs; ++i) {
pTmpHeader[i]._lOffset = pTmpHeader[i]._lLength = 0;
pTmpHeader[i]._lCrc = pTmpHeader[i]._lKey = 0;
}
if (_pHeader != nullptr) {
memcpy(pTmpHeader, _pHeader, (size_t)(HeaderRec::size() * (_lNumRecs - 1)));
delete[] _pHeader;
}
_pHeader = pTmpHeader;
int32 lRecNum = _lNumRecs - 1;
HeaderRec *pCurRec = &_pHeader[lRecNum];
int32 lPrevLength = HeadInfo::size();
int32 lPrevOffset = 0;
if (lRecNum != 0) {
lPrevLength = _pHeader[lRecNum - 1]._lLength;
lPrevOffset = _pHeader[lRecNum - 1]._lOffset;
}
pCurRec->_lLength = lLength;
pCurRec->_lOffset = lPrevOffset + lPrevLength;
writeRecord(lRecNum, pBuf, lLength, bUpdateHeader, lKey);
}
}
}
return _errCode;
}
int32 CBofDataFile::findRecord(uint32 lKey) {
assert(isValidObject(this));
// Assume no match
int32 lRecNum = -1;
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Scan the header for the key matching the hash code
for (int32 i = 0; i < _lNumRecs; i++) {
// Header records must be valid
assert(_pHeader != nullptr);
if (_pHeader[i]._lKey == lKey) {
lRecNum = i;
break;
}
}
}
return lRecNum;
}
int32 CBofDataFile::getRecSize(int32 lRecNum) {
assert(isValidObject(this));
int32 lSize = -1;
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Validate record number
assert(lRecNum >= 0 && lRecNum < _lNumRecs);
assert(_pHeader != nullptr);
lSize = _pHeader[lRecNum]._lLength;
}
return lSize;
}
int32 CBofDataFile::getMaxRecSize() const {
assert(isValidObject(this));
int32 lLargest = -1;
// Only continue if there is no current error
if (_errCode == ERR_NONE) {
// Validate header
assert(_pHeader != nullptr);
for (int i = 0; i < (int)_lNumRecs; i++) {
lLargest = MAX(lLargest, _pHeader[i]._lLength);
}
}
return lLargest;
}
void CBofDataFile::setPassword(const char *pszPassword) {
assert(isValidObject(this));
_szPassWord[0] = '\0';
if (pszPassword != nullptr) {
assert(strlen(pszPassword) < MAX_PW_LEN);
Common::strcpy_s(_szPassWord, pszPassword);
}
}
ErrorCode CBofDataFile::read(void *pDestBuf, int32 lBytes) {
return CBofFile::read(pDestBuf, lBytes);
}
ErrorCode CBofDataFile::read(HeadInfo &rec) {
byte buf[16];
ErrorCode errorCode = read(&buf[0], 16);
Common::MemoryReadStream mem(buf, 16);
Common::Serializer s(&mem, nullptr);
rec.synchronize(s);
return errorCode;
}
ErrorCode CBofDataFile::read(HeaderRec &rec) {
byte buf[16];
ErrorCode errorCode = read(&buf[0], 16);
Common::MemoryReadStream mem(buf, 16);
Common::Serializer s(&mem, nullptr);
rec.synchronize(s);
return errorCode;
}
ErrorCode CBofDataFile::write(const void *pSrcBuf, int32 lBytes) {
return CBofFile::write(pSrcBuf, lBytes);
}
ErrorCode CBofDataFile::write(HeadInfo &rec) {
byte buf[16];
Common::MemoryWriteStream mem(buf, 16);
Common::Serializer s(nullptr, &mem);
rec.synchronize(s);
return write(&buf[0], 16);
}
ErrorCode CBofDataFile::write(HeaderRec &rec) {
byte buf[16];
Common::MemoryWriteStream mem(buf, 16);
Common::Serializer s(nullptr, &mem);
rec.synchronize(s);
return write(&buf[0], 16);
}
/**
* Builds a Hash code based on a key.
* @param pKey Key
* @return Hash code
*/
uint32 CreateHashCode(const byte *pKey) {
// validate input
assert(pKey != nullptr);
uint32 lCode = ((uint32) * pKey << 24) | ((uint32) * (pKey + 1) << 16) | ((uint32) * (pKey + 2) << 8) | *(pKey + 3);
return lCode;
}
void SwapHeadInfo(HeadInfo *stHI) {
// Macintosh is big endian, so we must swap our bytes
stHI->_lNumRecs = SWAPLONG(stHI->_lNumRecs);
stHI->_lAddress = SWAPLONG(stHI->_lAddress);
stHI->_lFlags = SWAPLONG(stHI->_lFlags);
stHI->_lFootCrc = SWAPLONG(stHI->_lFootCrc);
}
void SwapHeaderRec(HeaderRec *stHR, int nRecords) {
HeaderRec *p = stHR;
for (int i = 0; i < nRecords; i++) {
p->_lOffset = SWAPLONG(p->_lOffset);
p->_lLength = SWAPLONG(p->_lLength);
p->_lCrc = SWAPLONG(p->_lCrc);
p->_lKey = SWAPLONG(p->_lKey);
p++;
}
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,245 @@
/* 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 BAGEL_BOFLIB_DAT_FILE_H
#define BAGEL_BOFLIB_DAT_FILE_H
#include "common/serializer.h"
#include "bagel/spacebar/boflib/file.h"
namespace Bagel {
namespace SpaceBar {
#define CDF_NOFLAGS 0x00000000
#define CDF_READONLY CBF_READONLY // Open for Read-only access
#define CDF_OVERWRITE CBF_OVERWRITE // *Overwrite any existing data-file
#define CDF_SHARED CBF_SHARED // *Open for Shared access
#define CDF_CREATE CBF_CREATE // *Create new file if not exist
#define CDF_SAVEFILE CBF_SAVEFILE
#define CDF_MEMORY 0x00010000 // *header/footer should stay in memory
#define CDF_ENCRYPT 0x00020000 // Specifies if data should use encryption
#define CDF_KEEPOPEN 0x00040000 // File should be kept open after construction
#define CDF_COMPRESSED 0x00080000 // *Specifies if data should be compressed
// * = indicates feature not yet implemented
#define CDF_DEFAULT (CDF_MEMORY | CDF_ENCRYPT | CDF_SHARED | CDF_KEEPOPEN | CDF_READONLY)
#define MAX_PW_LEN 32 // Max Password length
struct HeaderRec {
public:
int32 _lOffset;
int32 _lLength;
uint32 _lCrc;
uint32 _lKey;
void synchronize(Common::Serializer &s);
static int size() {
return 16;
}
};
struct HeadInfo {
int32 _lNumRecs; // Number of records in this file
int32 _lAddress; // starting address of footer
uint32 _lFlags; // contains flags for this file
uint32 _lFootCrc; // CRC of the footer
void synchronize(Common::Serializer &s);
static int size() {
return 16;
}
};
class CBofDataFile : public CBofFile {
private:
char _szPassWord[MAX_PW_LEN];
int32 _lHeaderLength = 0;
int32 _lHeaderStart = 0;
int32 _lNumRecs = 0;
HeaderRec *_pHeader = nullptr;
bool _bHeaderDirty;
protected:
/**
* Read the header (actually a footer) from the data-file.
* @return Error return code
*/
ErrorCode readHeader();
/**
* Writes the header (actually a footer) to the data-file.
* @return Error return code
*/
ErrorCode writeHeader();
public:
/**
* Constructor
*/
CBofDataFile();
/**
* Destructor
*/
virtual ~CBofDataFile();
/**
* Initializes a CBofDataFile with specified info
* @param pszFileName Name of .DAT file
* @param lFlags Flags for open, and encryption, etc.
* @return Error return code
*/
ErrorCode setFile(const char *pszFileName, uint32 lFlags);
/**
* Free memory used by this object
* @return Error return code
*/
ErrorCode releaseFile();
/**
* Retrieves size of specified record.
* @param lRecNum Index of record to get size of
* @return Size of specified record
*/
int32 getRecSize(int32 lRecNum);
int32 getNumberOfRecs() const {
return _lNumRecs;
}
/**
* Retrieves size of the largest record.
* @return Size of largest record in the data-file
*/
int32 getMaxRecSize() const;
/**
* Opens an existing data-file, or creates a new one.
* @return Error return code
*/
ErrorCode open();
/**
* Closes current data-file, if it's not already closed
* @return Error return code
*/
ErrorCode close() override;
/**
* Destroys current data-file, if any, and starts a new empty one
* @return Error return code
*/
ErrorCode create();
/**
* Reads specified record from data-file.
* @param lRecNum Record number to read
* @param pBuf Buffer to store record
* @return Error return code
*/
ErrorCode readRecord(int32 lRecNum, void *pBuf);
/**
* Read a set number of bytes from the beginning of a file,
* don't bother with a CRC, but decrypt if necessary. This is dependent upon
* the decryption being based on a single byte ordering scheme.
*/
ErrorCode readFromFile(int32 lRecNum, void *pBuf, int32 lBytes);
/**
* Writes specified to data-file.
* @param lRecNum Record number to read
* @param pBuf Buffer to write data from
* @param lSize Size of buffer
* @param bUpdateHeader True if header is to be committed to disk
* @param lKey Hash key
* @return Error return code
*/
ErrorCode writeRecord(int32 lRecNum, void *pBuf, int32 lSize = -1, bool bUpdateHeader = false, uint32 lKey = 0xFFFFFFFF);
/**
* Verifies specified record in data-file.
* @param lRecNum Record number to verify
* @return Error return code
*/
ErrorCode verifyRecord(int32 lRecNum);
/**
* Verifies all records in this file
* @return Error return code
*/
ErrorCode verifyAllRecords();
/**
* Adds a new record to the data-file.
* @param pBuf Buffer to write data from
* @param lLength Size of buffer
* @param bUpdateHeader true if header is to be committed to disk
* @param lKey hash Key
* @return Error return code
*/
ErrorCode addRecord(void *pBuf, int32 lLength, bool bUpdateHeader = false, uint32 lKey = 0xFFFFFFFF);
/**
* Finds record by it's key.
* @param lKey Key to search records with
* @return Index of record matching key, or -1
*/
int32 findRecord(uint32 lKey);
/**
* Sets encryption password
* @param pszPassword New password
*/
void setPassword(const char *pszPassword);
const char *getPassword() const {
return _szPassWord;
}
/**
* Read from a currently open file
* @param pDestBuf Destination buffer
* @param lBytes Number of bytes
* @return Error code
*/
ErrorCode read(void *pDestBuf, int32 lBytes) override;
ErrorCode read(HeaderRec &rec);
ErrorCode read(HeadInfo &rec);
/**
* Write to a currently open file
* @param pSrcBuf Source buffer
* @param lBytes Number of bytes
* @return Error code
*/
ErrorCode write(const void *pSrcBuf, int32 lBytes) override;
ErrorCode write(HeaderRec &rec);
ErrorCode write(HeadInfo &rec);
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,51 @@
/* 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/>.
*
*/
#include "common/config-manager.h"
#include "common/debug.h"
#include "bagel/spacebar/boflib/debug.h"
#include "bagel/bagel.h"
namespace Bagel {
namespace SpaceBar {
CBofDebugOptions *g_pDebugOptions = nullptr;
CBofDebugOptions::CBofDebugOptions(const char *pszFileName) : CBofOptions(pszFileName) {
// Add programmer definable debug options here
ConfMan.registerDefault("AbortsOn", true);
ConfMan.registerDefault("MessageBoxOn", true);
ConfMan.registerDefault("RandomOn", true);
ConfMan.registerDefault("DebugLevel", gDebugLevel);
ConfMan.registerDefault("ShowIO", false);
ConfMan.registerDefault("MessageSpy", false);
readSetting("DebugOptions", "AbortsOn", &_bAbortsOn, ConfMan.getBool("AbortsOn"));
readSetting("DebugOptions", "MessageBoxOn", &_bMessageBoxOn, ConfMan.getBool("MessageBoxOn"));
readSetting("DebugOptions", "RandomOn", &_bRandomOn, ConfMan.getBool("RandomOn"));
readSetting("DebugOptions", "DebugLevel", &_nDebugLevel, ConfMan.getInt("DebugLevel"));
readSetting("DebugOptions", "ShowIO", &_bShowIO, ConfMan.getBool("ShowIO"));
readSetting("DebugOptions", "MessageSpy", &_bShowMessages, ConfMan.getBool("MessageSpy"));
}
} // namespace SpaceBar
} // namespace Bagel

Some files were not shown because too many files have changed in this diff Show More