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

1
engines/bagel/POTFILES Normal file
View File

@@ -0,0 +1 @@
engines/bagel/metaengine.cpp

33
engines/bagel/afxwin.h Normal file
View File

@@ -0,0 +1,33 @@
/* 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_AFXWIN_H
#define BAGEL_AFXWIN_H
#include "bagel/mfc/mfc.h"
namespace Bagel {
using namespace Bagel::MFC;
} // namespace Bagel
#endif

75
engines/bagel/bagel.cpp Normal file
View File

@@ -0,0 +1,75 @@
/* 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/bagel.h"
#include "bagel/detection.h"
#include "backends/keymapper/keymapper.h"
namespace Bagel {
BagelEngine *g_engine;
BagelEngine::BagelEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Bagel") {
g_engine = this;
}
BagelEngine::~BagelEngine() {
delete _midi;
}
uint32 BagelEngine::getFeatures() const {
return _gameDescription->flags;
}
Common::String BagelEngine::getGameId() const {
return _gameDescription->gameId;
}
Common::Platform BagelEngine::getPlatform() const {
return _gameDescription->platform;
}
bool BagelEngine::isDemo() const {
return (_gameDescription->flags & ADGF_DEMO) != 0;
}
bool BagelEngine::isMazeODoomDemo() const {
return !strcmp(_gameDescription->gameId, "mazeodoom");
}
SaveStateList BagelEngine::listSaves() const {
return getMetaEngine()->listSaves(_targetName.c_str());
}
bool BagelEngine::savesExist() const {
return !listSaves().empty();
}
void BagelEngine::errorDialog(const char *msg) const {
GUIErrorMessage(msg);
}
void BagelEngine::enableKeymapper(bool enabled) {
getEventManager()->getKeymapper()->setEnabled(enabled);
}
} // End of namespace Bagel

117
engines/bagel/bagel.h Normal file
View File

@@ -0,0 +1,117 @@
/* 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_H
#define BAGEL_H
#include "common/random.h"
#include "graphics/screen.h"
#include "bagel/detection.h"
#include "bagel/music.h"
#include "bagel/spacebar/baglib/master_win.h"
namespace Bagel {
struct BagelGameDescription;
class BagelEngine : public Engine {
private:
const ADGameDescription *_gameDescription;
Common::RandomSource _randomSource;
public:
bool _useOriginalSaveLoad = false;
SpaceBar::CBagMasterWin *_masterWin = nullptr;
CBofPoint g_cInitLoc; // This is the initial location for the next new pan (only option at this point)
bool g_bUseInitLoc = false;
bool g_getVilVarsFl = true;
MusicPlayer *_midi = nullptr;
public:
BagelEngine(OSystem *syst, const ADGameDescription *gameDesc);
~BagelEngine() override;
uint32 getFeatures() const;
/**
* Returns the game Id
*/
Common::String getGameId() const;
/**
* Return if the game is Space Bar
*/
bool isSpaceBar() const {
return getGameId() == "spacebar";
}
/**
* Return the game's platform
*/
Common::Platform getPlatform() const;
/**
* Return whether it's a demo
*/
bool isDemo() const;
bool isMazeODoomDemo() const;
/**
* Gets a random number
*/
uint32 getRandomNumber(uint maxNum = 0x7fffffff) {
return _randomSource.getRandomNumber(maxNum);
}
bool hasFeature(EngineFeature f) const override {
return
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime) ||
(f == kSupportsReturnToLauncher);
};
/**
* Returns a list of savegames
*/
SaveStateList listSaves() const;
/**
* Returns true if any savegames exist
*/
bool savesExist() const;
virtual Graphics::Screen *getScreen() const = 0;
void errorDialog(const char *msg) const;
void enableKeymapper(bool enabled);
};
extern BagelEngine *g_engine;
#define SHOULD_QUIT ::Bagel::g_engine->shouldQuit()
inline int brand() {
return g_engine->getRandomNumber(RAND_MAX);
}
} // End of namespace Bagel
#endif // BAGEL_H

View File

@@ -0,0 +1,177 @@
/* 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/boflib/cache.h"
#include "bagel/boflib/log.h"
#include "bagel/spacebar/boflib/debug.h"
#include "bagel/boflib/misc.h"
namespace Bagel {
// Static members
CCache *CCache::_pCacheList;
uint32 CCache::_lOldest;
uint32 CCache::_lYoungest;
uint16 CCache::_nEntries;
void CCache::initialize() {
_pCacheList = nullptr;
_lOldest = 0xFFFFFFFF;
_lYoungest = 0xFFFFFFFF;
_nEntries = 0;
}
CCache::CCache() {
_bValid = true;
// Inits
_lAge = _lYoungest;
_bCached = false;
_nLockCount = 0;
if (_pCacheList == nullptr) {
// There can't be any other entries
assert(_nEntries == 0);
// This object is the start of the cache list
_pCacheList = this;
} else {
assert(_nEntries != 0);
_pCacheList->Insert(this);
}
// One more cached entry
_nEntries++;
}
CCache::~CCache() {
// Make sure this object is not deleted twice
assert(_bValid);
// There can be only one cache list per EXE/DLL
assert(this->getHead() == _pCacheList);
// Object must be released by the derived class destructor
assert(_bCached == false);
_nEntries--;
// Remove this object from the linked list
if (this == _pCacheList) {
_pCacheList = (CCache *)this->getNext();
}
this->Delete();
if (_nEntries == 0) {
_pCacheList = nullptr;
}
_bValid = false;
}
bool CCache::flush() {
bool bReleased = false;
CCache *pCache = _pCacheList;
while (pCache != nullptr) {
if (pCache->release())
bReleased = true;
pCache = (CCache *)(pCache->getNext());
}
return bReleased;
}
bool CCache::optimize(uint32 lRequestedFreeSpace) {
logInfo(buildString("CCache::optimize(%u)", lRequestedFreeSpace));
bool bSuccess = true;
while (getFreePhysMem() < lRequestedFreeSpace) {
uint32 lAvgAge = ((_lOldest - _lYoungest) / 2) + _lYoungest;
_lOldest = lAvgAge;
// Parse Linked list of cached objects and remove any that are too old
CCache *pCache = _pCacheList;
int nObjects = 0;
while (pCache != nullptr) {
if (pCache->_bCached && (pCache->_nLockCount <= 0)) {
nObjects++;
if (pCache->_lAge >= lAvgAge) {
logInfo(buildString("Freeing Object: %p from the Cache list", pCache));
pCache->release();
}
}
// Next object in list
pCache = (CCache *)pCache->getNext();
}
// If there are no objects loaded then we really might be out of memory
if (nObjects == 0) {
bSuccess = false;
break;
}
}
return bSuccess;
}
void CCache::load() {
// Make sure this object is not used after it is destructed
assert(_bValid);
// Timestamp this object
_lAge = --_lYoungest;
// If this object is not already cached
if (!_bCached) {
// We must tell the Cache library that this object is in the cache to avoid recursion
_bCached = true;
// Call the routine that will allocate the memory for this object
// alloc() is pure-virtual and must be defined in the derived class.
_bCached = alloc();
}
}
bool CCache::release() {
// Make sure this object is not used after it is destructed
assert(_bValid);
// If this object is in the cache
bool bReleased = false;
if (_bCached) {
bReleased = true;
// Call the routine that will free the memory used by this object.
// free() is pure-virtual and must be defined in the derived class.
free();
_bCached = false;
}
return bReleased;
}
} // namespace Bagel

View File

@@ -0,0 +1,101 @@
/* 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_CACHE_H
#define BAGEL_BOFLIB_CACHE_H
#include "bagel/boflib/llist.h"
#include "bagel/boflib/stdinc.h"
namespace Bagel {
class CCache : private CLList {
private:
virtual bool alloc() = 0; // These pure-virtuals MUST be defined
virtual void free() = 0; // in the derived class.
static CCache *_pCacheList; // Linked cache list
static uint32 _lOldest; // Current oldest object in cache
static uint32 _lYoungest; // Current youngest object in cache
static uint16 _nEntries; // Number of CCache Objects
uint32 _lAge; // Age of this object
int _nLockCount; // # of locks held on this object
bool _bCached; // true if object is in the cache
bool _bValid; // true if this object is valid
public:
/**
* Constructor
*/
CCache();
/**
* Destructor
*/
virtual ~CCache();
/**
* Loads current object into cache
*/
void load();
/**
* Releases current object from cache
*/
bool release();
void lock() {
_nLockCount++;
load();
}
void unlock() {
_nLockCount--;
}
bool isLocked() {
return (_nLockCount > 0);
}
/**
* initialize statics
*/
static void initialize();
/**
* Releases all objects from cache
*/
static bool flush();
/**
* Releases older objects from cache if need memory
* @remarks Optimizes cache so that the specified amount of memory is left available.
* @param lRequestedFreeSpace Free space requested to remain available
* @return true if there were any objects to release from the cache.
* false if there were no objects released.
*/
static bool optimize(uint32 lRequestedFreeSpace);
};
} // namespace Bagel
#endif

View File

@@ -0,0 +1,50 @@
/* 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/boflib/cursor_data.h"
namespace Bagel {
const byte ARROW_CURSOR[CURSOR_W * CURSOR_H] = {
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0,
1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0,
1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0,
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0,
1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0,
1, 2, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0,
1, 2, 1, 0, 0, 1, 2, 2, 1, 0, 0, 0,
1, 1, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0,
0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
};
const byte CURSOR_PALETTE[9] = { 0x80, 0x80, 0x80, 0, 0, 0, 0xff, 0xff, 0xff };
} // namespace Bagel

View File

@@ -0,0 +1,38 @@
/* 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_CURSOR_DATA_H
#define BAGEL_BOFLIB_CURSOR_DATA_H
#include "common/scummsys.h"
namespace Bagel {
constexpr int CURSOR_W = 12;
constexpr int CURSOR_H = 20;
extern const byte ARROW_CURSOR[CURSOR_W * CURSOR_H];
extern const byte CURSOR_PALETTE[9];
} // namespace Bagel
#endif

View File

@@ -0,0 +1,103 @@
/* 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/str.h"
#include "gui/debugger.h"
#include "bagel/boflib/error.h"
#include "bagel/bagel.h"
namespace Bagel {
const char *const g_errList[] = {
"No Error",
"Out of memory",
"Error opening file",
"Error closing file",
"Error reading file",
"Error writing file",
"Error seeking file",
"Error deleting file",
"Could not find file",
"Invalid file type",
"Invalid Path",
"Disk error",
"Unknown Error",
"CRC failure"
};
// Static members
//
int CBofError::_count;
CBofError::CBofError() {
_errCode = ERR_NONE;
}
void CBofError::initialize() {
_count = 0;
}
void CBofError::reportError(ErrorCode errCode, const char *format, ...) {
_errCode = errCode;
if (_errCode == ERR_NONE)
return;
Common::String buf;
// One more error
_count++;
// Don't parse the variable input if there isn't any
if (format != nullptr) {
// Parse the arguments
va_list argptr;
va_start(argptr, format);
buf = Common::String::vformat(format, argptr);
va_end(argptr);
}
// Tell user about error, unless there were too many errors
if (_count < MAX_ERRORS)
bofMessageBox(buf, g_errList[errCode]);
GUI::Debugger *console = g_engine->getDebugger();
if (console->isActive())
console->debugPrintf("%s\n", buf.c_str());
}
void CBofError::fatalError(ErrorCode errCode, const char *format, ...) {
Common::String buf;
// Don't parse the variable input if there isn't any
if (format != nullptr) {
// Parse the arguments
va_list argptr;
va_start(argptr, format);
buf = Common::String::vformat(format, argptr);
va_end(argptr);
}
error("%s - %s", g_errList[errCode], buf.c_str());
}
} // namespace Bagel

View File

@@ -0,0 +1,103 @@
/* 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_ERROR_H
#define BAGEL_BOFLIB_ERROR_H
#include "common/str.h"
namespace Bagel {
/**
* Error reporting codes
*/
enum ErrorCode {
ERR_NONE = 0, /* no error */
ERR_MEMORY = 1, /* not enough memory */
ERR_FOPEN = 2, /* error opening a file */
ERR_FREAD = 4, /* error reading a file */
ERR_FWRITE = 5, /* error writing a file */
ERR_FSEEK = 6, /* error seeking a file */
ERR_FFIND = 8, /* could not find file */
ERR_FTYPE = 9, /* invalid file type */
ERR_UNKNOWN = 12, /* unknown error */
ERR_CRC = 13, /* file or data failed CRC check */
};
#define ERROR_CODE ErrorCode
#define MAX_ERRORS 3
extern const char *const g_errList[];
#define errList g_errList
class CBofError {
protected:
static int _count;
ErrorCode _errCode;
virtual void bofMessageBox(const Common::String &content, const Common::String &title) {
}
public:
CBofError();
virtual ~CBofError() {
}
/**
* Logs specified error to log file.
* @remarks Sets _errCode to specified error condition, and logs the
* error.
* @param errCode Error to report
* @param format A printf style format string
* @param ... Additional parameters to be formatted and inserted into the string
*/
void reportError(ErrorCode errCode, const char *format, ...);
/**
* Logs specified fatal error to log file and exit the game.
* @param errCode Error to report
* @param format A printf style format string
* @param ... Additional parameters to be formatted and inserted into the string
*/
static void fatalError(ErrorCode errCode, const char *format, ...);
bool errorOccurred() const {
return _errCode != ERR_NONE;
}
ErrorCode getErrorCode() const {
return _errCode;
}
void clearError() {
_errCode = ERR_NONE;
}
static void initialize();
static int getErrorCount() {
return _count;
}
};
} // namespace Bagel
#endif

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/>.
*
*/
#include "common/events.h"
#include "bagel/boflib/event_loop.h"
#include "bagel/bagel.h"
#include "bagel/spacebar/baglib/master_win.h"
namespace Bagel {
EventLoop::EventLoop(Mode mode) : _limiter(g_system, 60, false),
_mode(mode) {
}
bool EventLoop::frame() {
Common::Event e;
// Handle pending events
while (g_system->getEventManager()->pollEvent(e)) {
if (g_engine->shouldQuit() || (e.type == Common::EVENT_LBUTTONDOWN) ||
(e.type == Common::EVENT_KEYDOWN && e.kbd.keycode == Common::KEYCODE_ESCAPE))
return true;
}
_limiter.delayBeforeSwap();
// Update the screen
if (_mode == FORCE_REPAINT && g_engine->isSpaceBar())
SpaceBar::CBagMasterWin::forcePaintScreen();
g_engine->getScreen()->update();
_limiter.startFrame();
return false;
}
} // 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_BOFLIB_EVENT_LOOP_H
#define BAGEL_BOFLIB_EVENT_LOOP_H
#include "graphics/framelimiter.h"
namespace Bagel {
class EventLoop {
public:
enum Mode {
NO_UPDATES = 0, FORCE_REPAINT = 1
};
private:
Graphics::FrameLimiter _limiter;
Mode _mode;
public:
EventLoop(Mode mode = NO_UPDATES);
/**
* Processes pending events and does a frame output.
* @returns True if Escape was pressed to abort loop
*/
bool frame();
};
} // namespace Bagel
#endif

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/>.
*
*/
#include "common/system.h"
#include "common/savefile.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/macresman.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/bagel.h"
#include "bagel/afxwin.h"
namespace Bagel {
bool fileExists(const char *pszFileName) {
if (g_engine->getPlatform() == Common::kPlatformMacintosh) {
return Common::MacResManager::exists(pszFileName);
} else if (!g_engine->isSpaceBar()) {
return MFC::FileExists(pszFileName);
} else {
return Common::File::exists(pszFileName);
}
}
int32 fileLength(const char *pszFileName) {
Common::SeekableReadStream *stream = nullptr;
if (g_engine->getPlatform() == Common::kPlatformMacintosh) {
stream = Common::MacResManager::openFileOrDataFork(pszFileName);
} else {
stream = SearchMan.createReadStreamForMember(pszFileName);
}
int32 length = -1;
if (stream) {
length = stream->size();
delete stream;
}
return length;
}
char *fileGetFullPath(char *pszDstBuf, const char *pszSrcBuf) {
Common::strcpy_s(pszDstBuf, MAX_DIRPATH, pszSrcBuf);
return pszDstBuf;
}
void fixPathName(CBofString &s) {
// Remove any homedir prefix. In ScummVM, all paths are relative
// to the game folder automatically
char *p = strstr(s.getBuffer(), HOMEDIR_TOKEN);
if (p != nullptr)
s = p + strlen(HOMEDIR_TOKEN) + 1;
// Replace any backslashes with forward slashes
while ((p = strchr(s.getBuffer(), '\\')) != nullptr)
* p = '/';
}
const char *formPath(const char *dir, const char *pszFile) {
assert(dir != nullptr && pszFile != nullptr);
static char szBuf[MAX_DIRPATH];
CBofString cStr(dir);
fixPathName(cStr);
Common::Path path(cStr.getBuffer());
path = path.append(pszFile);
Common::strcpy_s(szBuf, path.toString().c_str());
return &szBuf[0];
}
} // 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_BOFLIB_FILE_FUNCTIONS_H
#define BAGEL_BOFLIB_FILE_FUNCTIONS_H
#include "common/scummsys.h"
#include "bagel/boflib/string.h"
namespace Bagel {
/**
* Checks to see if specified file exists
* @param pszFileName Name of file to check existence
* @return true if file exists, false if file does not exist
*
**/
// for mac, use this routine to replace the diskid
extern bool fileExists(const char *pszFileName);
/**
* Gets length of file in bytes (via file name)
* @param pszFileName Name of file to get length for
* @return Size of specified file (or -1 if not exist or error)
*/
extern int32 fileLength(const char *pszFileName);
extern char *fileGetFullPath(char *pszDstBuf, const char *pszSrcBuf);
/**
* Takes a directory and filename, merging them to form a
* fully qualified filename. Also takes care of special folder
* aliases at the start of the directory name
*/
extern const char *formPath(const char *dir, const char *pszFile);
extern void fixPathName(CBofString &s);
} // namespace Bagel
#endif

View File

@@ -0,0 +1,167 @@
/* 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/scummsys.h"
#include "bagel/boflib/llist.h"
namespace Bagel {
CLList::CLList() {
_pPrev = nullptr;
_pNext = nullptr;
_pData = nullptr;
}
CLList::CLList(void *pObj) {
_pPrev = nullptr;
_pNext = nullptr;
_pData = pObj;
}
CLList::~CLList() {
this->Delete();
}
void CLList::addToHead(CLList *pNewList) {
// Can't insert a nullptr record into the list
assert(pNewList != nullptr);
CLList *pListHead = getHead();
pNewList->_pNext = pListHead;
pNewList->_pPrev = nullptr;
pListHead->_pPrev = pNewList;
}
void CLList::addToTail(CLList *pNewList) {
// Can't insert a nullptr record into the list
assert(pNewList != nullptr);
CLList *pListTail = getTail();
pNewList->_pPrev = pListTail;
pNewList->_pNext = nullptr;
pListTail->_pNext = pNewList;
}
void CLList::Insert(CLList *pList) {
// Can't insert a nullptr record into the list
assert(pList != nullptr);
pList->_pPrev = this;
pList->_pNext = _pNext;
if (_pNext != nullptr)
_pNext->_pPrev = pList;
_pNext = pList;
}
void CLList::Delete() {
if (_pPrev != nullptr)
_pPrev->_pNext = _pNext;
if (_pNext != nullptr)
_pNext->_pPrev = _pPrev;
_pPrev = _pNext = nullptr;
}
void CLList::MoveToHead() {
CLList *pHead = getHead();
assert(pHead != nullptr);
if (this != pHead) {
Delete();
pHead->addToHead(this);
}
}
void CLList::MoveToTail() {
CLList *pTail = getTail();
assert(pTail != nullptr);
if (this != pTail) {
Delete();
pTail->addToTail(this);
}
}
void CLList::MoveLeft() {
if (_pPrev != nullptr) {
CLList *pPrev = _pPrev->getPrev();
if (pPrev != nullptr) {
Delete();
pPrev->Insert(this);
} else {
MoveToHead();
}
}
}
void CLList::MoveRight() {
CLList *pNext = _pNext;
if (pNext != nullptr) {
this->Delete();
pNext->Insert(this);
}
}
void CLList::FlushList() {
CLList *pList = getHead();
// Something is wrong if the head is invalid
assert(pList != nullptr);
while (pList != nullptr) {
CLList *pTmpList = pList->_pNext;
// Don't delete myself
if (pList != this)
delete pList;
pList = pTmpList;
}
}
CLList *CLList::getHead() {
CLList *pList = this;
while (pList->_pPrev != nullptr)
pList = pList->_pPrev;
return pList;
}
CLList *CLList::getTail() {
CLList *pList = this;
while (pList->_pNext != nullptr)
pList = pList->_pNext;
return pList;
}
} // namespace Bagel

View File

@@ -0,0 +1,136 @@
/* 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_LLIST_H
#define BAGEL_BOFLIB_LLIST_H
namespace Bagel {
/**
* Linked list class
*/
class CLList {
protected:
CLList *_pPrev; // Pointer to next link in chain
CLList *_pNext; // Pointer to previous link in chain
void *_pData; // Pointer to owning CData
public:
/**
* Default constructor
*/
CLList();
/**
* Alternate constructor that initializes with specified data
*/
CLList(void *pObj);
/**
* Destructor
*/
virtual ~CLList();
/**
* Links specified node to current list after current node
* @remarks This will link a new list into the current right after the current node
* @param pNewList Pointer to list to be inserted
*/
void Insert(CLList *pNewList);
/**
* Deletes current node
*/
void Delete();
/**
* Links specified node to head of list
* @remarks This can be used to link 2 lists together by Linking the
* tail of one list to the head of another
* @param pNewList New list to link to head of current list
*/
void addToHead(CLList *pNewList);
/**
* Links specified node to tail of current list
* @remarks This can be used to link 2 lists together by Linking the
* head of one list to the tail of another
* @param pNewList Pointer to new list
*/
void addToTail(CLList *pNewList);
/**
* Moves this item to the head of the linked list
*/
void MoveToHead();
/**
* Moves this item to the tail of the linked list
*/
void MoveToTail();
/**
* Moves this item 1 item to the left
*/
void MoveLeft();
/**
* Moves this item 1 item to the right
*/
void MoveRight();
/**
* Returns head of current list
* @return Pointer to head of list
*/
CLList *getHead();
/**
* Returns tail of current list
* @return Pointer to tail of list
*/
CLList *getTail();
CLList *getPrev() const {
return _pPrev;
}
CLList *getNext() const {
return _pNext;
}
void *getData() const {
return _pData;
}
void PutData(void *pObj) {
_pData = pObj;
}
/**
* Flushes entire list
*/
void FlushList();
};
} // namespace Bagel
#endif

View File

@@ -0,0 +1,69 @@
/* 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/system.h"
#include "common/savefile.h"
#include "common/debug.h"
#include "bagel/boflib/log.h"
namespace Bagel {
static const char *const g_pszLogTypes[4] = {
"Fatal Error: ",
"Error: ",
"Warning: ",
""
};
void logInfo(const char *msg) {
if (gDebugLevel > 0)
debug("%s", msg);
}
void logWarning(const char *msg) {
if (gDebugLevel > 0)
debug("%s%s", g_pszLogTypes[2], msg);
}
void logError(const char *msg) {
if (gDebugLevel > 0)
debug("%s%s", g_pszLogTypes[1], msg);
}
const char *buildString(const char *pszFormat, ...) {
static char szBuf[256];
va_list argptr;
assert(pszFormat != nullptr);
if (pszFormat != nullptr) {
// Parse the variable argument list
va_start(argptr, pszFormat);
Common::vsprintf_s(szBuf, pszFormat, argptr);
va_end(argptr);
return (const char *)&szBuf[0];
}
return nullptr;
}
} // namespace Bagel

View File

@@ -0,0 +1,40 @@
/* 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_LOG_H
#define BAGEL_BOFLIB_LOG_H
namespace Bagel {
/**
* Builds a string like sprintf()
* @return Pointer to new (temporary) buffer.
*/
const char *buildString(const char *pszFormat, ...);
extern void logInfo(const char *msg);
extern void logWarning(const char *msg);
extern void logError(const char *msg);
} // namespace Bagel
#endif

View File

@@ -0,0 +1,523 @@
/* 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/misc.h"
#include "bagel/boflib/cache.h"
#include "bagel/bagel.h"
#include "bagel/boflib/string_functions.h"
namespace Bagel {
#define MAX_LINE_LEN 100
static uint32 lStart;
void timerStart() {
lStart = g_system->getMillis();
}
uint32 timerStop() {
return g_system->getMillis() - lStart;
}
uint32 getTimer() {
return g_system->getMillis();
}
void bofSleep(uint32 milli) {
g_system->delayMillis(milli);
}
#define ALLOC_FAIL_RETRIES 2
void *bofMemAlloc(uint32 nSize, const char *pFile, int nLine, bool bClear) {
// For now, until I fix it, pFile MUST be valid.
assert(pFile != nullptr);
assert(nSize != 0);
// Assume failure
void *pNewBlock = nullptr;
// Try a few times to allocate the desired amount of memory.
// Flush objects from Cache is necessary.
for (int nRetries = 0; nRetries < ALLOC_FAIL_RETRIES; nRetries++) {
pNewBlock = (void *)malloc(nSize);
// If allocation was successful, then we're outta here
if (pNewBlock != nullptr) {
if (bClear)
memset((byte *)pNewBlock, 0, nSize);
break;
}
// Otherwise, we need to free up some memory by flushing old
// objects from the Cache.
CCache::optimize(nSize + 2 * sizeof(uint16) + sizeof(uint32));
}
if (pNewBlock == nullptr)
CBofError::fatalError(ERR_MEMORY, "Could not allocate %u bytes, file %s, line %d", nSize, pFile, nLine);
return pNewBlock;
}
void bofMemFree(void *pBuf) {
free(pBuf);
}
Fixed fixedMultiply(Fixed Multiplicand, Fixed Multiplier) {
int64 nTmpNum = (int64)Multiplicand * Multiplier;
Fixed fixResult = (Fixed)(nTmpNum >> 16);
return fixResult;
}
Fixed fixedDivide(Fixed Dividend, Fixed Divisor) {
int64 nBigNum = (int64)Dividend << 16;
Fixed fixResult = (Fixed)(nBigNum / Divisor);
return fixResult;
}
void bofMemSet(void *pSrc, byte chByte, int32 lBytes) {
assert(pSrc != nullptr);
byte *pBuf = (byte *)pSrc;
while (lBytes-- != 0)
*pBuf++ = chByte;
}
void bofMemCopy(void *pDst, const void *pSrc, int32 lLength) {
assert(pDst != nullptr);
assert(pSrc != nullptr);
assert(lLength >= 0);
byte *p1 = (byte *)pDst;
const byte *p2 = (const byte *)pSrc;
while (lLength-- != 0) {
*p1++ = *p2++;
}
}
bool readLine(Common::SeekableReadStream *fp, char *pszBuf) {
if (fp->eos())
return false;
Common::String line = fp->readLine();
Common::strcpy_s(pszBuf, MAX_LINE_LEN, line.c_str());
strreplaceChar(pszBuf, '\n', '\0');
return true;
}
void encrypt(void *pBuf, int32 size, const char *pszPassword) {
assert(pBuf != nullptr);
const char *pStart = pszPassword;
if (!pszPassword || strlen(pszPassword) == 0) {
pStart = "\0\0";
}
byte *p = (byte *)pBuf;
const char *pPW = pStart;
while (--size >= 0) {
*p ^= (byte)(0xD2 + size + *pPW);
p++;
if (*pPW++ == '\0') {
pPW = pStart;
}
}
}
void encryptPartial(void *pBuf, int32 fullSize, int32 lBytes, const char *pszPassword) {
assert(pBuf != nullptr);
const char *pStart = pszPassword;
if (!pszPassword || strlen(pszPassword) == 0) {
pStart = "\0\0";
}
byte *p = (byte *)pBuf;
const char *pPW = pStart;
while (--lBytes >= 0) {
fullSize--;
*p ^= (byte)(0xD2 + fullSize + *pPW);
p++;
if (*pPW++ == '\0') {
pPW = pStart;
}
}
}
int mapWindowsPointSize(int pointSize) {
return pointSize;
}
void ErrorLog(const char *logFile, const char *format, ...) {
// No implementation
}
int StrFreqMatch(const char *mask, const char *test) {
static int nCount[256];
int i, divergence;
/* can't access null pointers */
assert(mask != nullptr);
assert(test != nullptr);
/* assume no match by making the divergence really high */
divergence = 100;
/*
* the first letter has to match before we even think about continuing
*/
if (*mask == *test) {
/* reset the frequency count */
memset(nCount, 0, sizeof(int) * 256);
/* count the frequency of the chars in 'mask' */
while (*mask != '\0')
nCount[(int)*mask++] += 1;
/* subtract off the frequency of the chars in 'test' */
while (*test != '\0')
nCount[(int)*test++] -= 1;
/*
* total all of the frequencies
*/
divergence = 0;
for (i = 0; i <= 255; i++)
divergence += abs(nCount[i]);
}
/* returning a 0 or 1 means that the strings are almost identical */
return (divergence);
}
bool StrCompare(const char *pszStr1, const char *pszStr2, unsigned int nSize) {
char *s1, *p, string1[256]; /* replace this stack hog with malloc */
char *s2, *sp, string2[256]; /* replace this stack hog with malloc */
int i, n, inc;
bool bMatch;
/* can't access null pointers */
assert(pszStr1 != nullptr);
assert(pszStr2 != nullptr);
/* make sure that we are not going to blow the stack */
assert(strlen(pszStr1) < 256);
assert(strlen(pszStr2) < 256);
p = s1 = string1;
s2 = string2;
/*
* Reset these buffers to garuntee the strings will terminate
*/
memset(s1, 0, 256);
memset(s2, 0, 256);
/* make local copies of the strings */
Common::sprintf_s(s1, 256, " %s", pszStr1);
Common::sprintf_s(s2, 256, " %s", pszStr2);
/*
* make "THE", "AN", and "A" be special tokens - make them uppercase while
* all other words are lowercase.
*/
strLower(s1);
StrUprStr(s1, " the ");
StrUprStr(s1, " an ");
StrUprStr(s1, " a ");
if ((sp = strstr(s2, " THE ")) != nullptr) {
memmove(sp, sp + 5, strlen(sp + 5) + 1);
}
/*
* strip out all unwanted characters
*/
/* strip out all spaces
*/
StrStripChar(s1, ' ');
StrStripChar(s2, ' ');
/* strip out any apostrophes
*/
StrStripChar(s1, 39);
StrStripChar(s2, 39);
/* strip out any commas
*/
StrStripChar(s1, ',');
StrStripChar(s2, ',');
/* strip out any dashes
*/
StrStripChar(s1, '-');
StrStripChar(s2, '-');
/*
* add a buffer zone to the end of both strings
* (this might now be obsolete)
*/
Common::strcat_s(s1, 256, " ");
Common::strcat_s(s2, 256, " ");
/*
* compare the 2 strings, if we get a "THE", "A", or "AN" (case sensative)
* then do a special compare
*/
/* assume they match */
bMatch = true;
i = 0;
n = strlen(s1);
while (i++ < n) {
/*
* handle special tokens
*/
if ((*s1 == 'T') || (*s1 == 'A')) {
inc = 3;
if (*s1 == 'A') {
inc = 1;
if (*(s1 + 1) == 'N') {
inc = 2;
}
}
p = s1;
if (toupper(*s1) != toupper(*s2)) {
s1 += inc;
i += inc;
} else {
p = s1 + inc;
i += inc;
}
}
if ((toupper(*s1) != toupper(*s2)) && (toupper(*p) != toupper(*s2))) {
bMatch = false;
break;
}
s1++;
s2++;
p++;
}
return (bMatch);
}
/*****************************************************************************
*
* StrCharCount - Counts number of occurences of a specified char in String
*
* DESCRIPTION: Counts the number of times the specified character occurs
* in the given string.
*
* SAMPLE USAGE:
* n = StrCharCount(str, c);
* const char *str; pointer to string to parse
* char c; character to count in str
*
* RETURNS: int = number of times character c occurs in string str
*
*****************************************************************************/
int StrCharCount(const char *str, char c) {
int n;
assert(str != nullptr);
assert(strlen(str) <= 255);
n = 0;
while (*str != '\0') {
if (*str++ == c)
n++;
}
return (n);
}
/**
* name StriStr - same as strstr() except ignores case
*
* synopsis s = StriStr(s1, s2)
* const char *s1 string to parse
* const char *s2 substring to find in s1
*
* purpose To search for a string inside another string while ignoring case
*
*
* returns pointer to substring s2 in s1 or nullptr if not found
*
**/
char *StriStr(char *s1, const char *s2) {
char *p, str1[80];
char str2[80];
/* can't access null pointers */
assert(s1 != nullptr);
assert(s2 != nullptr);
/* make sure we don't blow the stack */
assert(strlen(s1) < 80);
assert(strlen(s2) < 80);
/* copy to local buffers */
Common::strcpy_s(str1, s1);
Common::strcpy_s(str2, s2);
/* convert to upper case */
strUpper(str1);
strUpper(str2);
/* find str2 in str1 */
p = strstr(str1, str2);
/* re-point to original string s1 */
if (p != nullptr) {
p = s1 + (p - str1);
}
return (p);
}
void StrUprStr(char *s1, const char *s2) {
char *p;
int i, n;
/* can't access null pointers */
assert(s1 != nullptr);
assert(s2 != nullptr);
p = s1;
while ((p = StriStr(p, s2)) != nullptr) {
n = strlen(s2);
for (i = 0; i < n; i++) {
*p = (char)toupper(*p);
p++;
}
}
}
/**
* name StrCpyStripChar - Same as Common::strcpy_s() except specified character
* will be stripped from the destination string.
*
* synopsis StrCpyStripChar(dest, source, c)
* char *dest destinaton string
* const char *source source string
* char c character to strip from dest
*
* purpose To strip out a specified character while copying 1 string to another
*
*
* returns Nothing
*
**/
void StrCpyStripChar(char *dest, const char *source, char c) {
/* can't access null pointers */
assert(dest != nullptr);
assert(source != nullptr);
/* source and destination cannot be the same */
assert(dest != source);
do {
if ((*dest = *source) != c)
dest++;
} while (*source++ != '\0');
}
char *StrStripChar(char *str, char c) {
char *p = str;
/* can't acces a null pointer */
assert(str != nullptr);
/* if c was '\0' then this function would do nothing */
assert(c != '\0');
while (*p != '\0') {
if (*p == c) {
/* move the string left 1 byte (including the terminator) */
memmove(p, p + 1, strlen(p + 1) + 1);
}
p++;
}
return (str);
}
char *StrReplaceChar(char *str, char cOld, char cNew) {
char *p = str;
/* can't acces a null pointer */
assert(str != nullptr);
/* if cOld was '\0' then this function would do nothing */
assert(cOld != '\0');
while (*p != '\0') {
if (*p == cOld) {
*p = cNew;
}
p++;
}
return (str);
}
/**
* name ProbableTrue
* synopsis - return a true / false based on the probability given
* int nProbability the probability of returning a true
*
* purpose to return a true <nProbability> of the tine
*
*
* returns bool
*
**/
bool ProbableTrue(int nProbability) {
int nRand = brand() % 100;
return (nRand < nProbability);
}
} // namespace Bagel

124
engines/bagel/boflib/misc.h Normal file
View File

@@ -0,0 +1,124 @@
/* 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_MISC_H
#define BAGEL_BOFLIB_MISC_H
#include "bagel/boflib/stdinc.h"
namespace Bagel {
extern int mapWindowsPointSize(int pointSize);
/**
* Starts a Millisecond timer
*/
extern void timerStart();
/**
* Stops the timer started by timerStart, returns time elapsed.
* @return Number of MilliSeconds elapsed since call to timerStart
*/
extern uint32 timerStop();
/**
* Returns the current elapsed time in milliseconds
*/
extern uint32 getTimer();
/**
* Pauses the computer for specified number of MilliSeconds
* @param milli Number of milliseconds
*/
extern void bofSleep(uint32 milli);
extern Fixed fixedDivide(Fixed Dividend, Fixed Divisor);
extern Fixed fixedMultiply(Fixed Multiplicand, Fixed Multiplier);
#define intToFixed(i) (Fixed)(((long)(i)) << 16)
#define fixedToInt(f) (int)(((long)(f)) >> 16)
//////////////////////////////////////////////////////////////////////////////
//
// Memory allocation routines (Should be put into their own MEMORY module)
//
//////////////////////////////////////////////////////////////////////////////
/**
* Allocates a memory block of specified size
* @param nSize Number of bytes to allocate
* @param pFile Source file name
* @param nLine Source file line number
* @param bClear true if buffer should be cleared
* @return Pointer to new buffer
*/
extern void *bofMemAlloc(uint32 nSize, const char *pFile, int nLine, bool bClear);
/**
* Frees specified memory block
* @param pBuf Buffer to de-allocate
**/
extern void bofMemFree(void *pBuf);
#define bofAlloc(n) bofMemAlloc((n), __FILE__, __LINE__, false)
#define bofCleanAlloc(n) bofMemAlloc((n), __FILE__, __LINE__, true)
#define bofFree(p) bofMemFree((p))
inline uint32 getFreePhysMem() {
return 999999;
}
/**
* Encrypts specified buffer
* @param pBuf Buffer to encrypt
* @param lSize Number of bytes in buffer
* @param pszPassword Optional password to encrypt with
*/
void encrypt(void *pBuf, int32 lSize, const char *pszPassword = nullptr);
#define decrypt encrypt
#define Decrypt encrypt
extern void encryptPartial(void *, int32, int32, const char *pPassword = nullptr);
#define decryptPartial encryptPartial
/**
* Return a true / false based on the probability given
* @param nProbability The probability of returning a true
* @returns True/false result
**/
extern bool ProbableTrue(int nProbability);
extern void ErrorLog(const char *logFile, const char *format, ...);
extern int StrFreqMatch(const char *, const char *);
extern bool StrCompare(const char *, const char *, unsigned int);
extern int StrCharCount(const char *, char);
extern char *StriStr(char *, const char *);
extern void StrUprStr(char *, const char *);
extern void StrCpyStripChar(char *, const char *, char);
extern char *StrStripChar(char *, char);
extern char *StrReplaceChar(char *, char, char);
} // namespace Bagel
#endif

View File

@@ -0,0 +1,40 @@
/* 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_OBJECT_H
#define BAGEL_BOFLIB_OBJECT_H
namespace Bagel {
class CBofObject {
public:
virtual ~CBofObject() {}
static bool isValidObject(const CBofObject *pObject) {
return true;
}
virtual void DeleteObject() {}
};
} // namespace Bagel
#endif

View File

@@ -0,0 +1,161 @@
/* 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 "graphics/palette.h"
#include "image/bmp.h"
#include "bagel/boflib/palette.h"
#include "bagel/spacebar/boflib/app.h"
#include "bagel/spacebar/boflib/file.h"
#include "bagel/boflib/file_functions.h"
namespace Bagel {
namespace SpaceBar {
CBofPalette *CBofPalette::_pSharedPalette;
char CBofPalette::_szSharedPalFile[MAX_FNAME];
PaletteData::PaletteData(int16 numColors) : _numColors(numColors) {
Common::fill(&_data[0], &_data[Graphics::PALETTE_SIZE], 0);
}
void CBofPalette::initialize() {
_pSharedPalette = nullptr;
_szSharedPalFile[0] = '\0';
}
CBofPalette::CBofPalette() {
Common::fill(&_palette._data[0], &_palette._data[Graphics::PALETTE_SIZE], 0);
}
CBofPalette::CBofPalette(const char *pszFileName) {
Common::fill(&_palette._data[0], &_palette._data[Graphics::PALETTE_SIZE], 0);
assert(pszFileName != nullptr);
loadPalette(pszFileName);
}
CBofPalette::CBofPalette(const PaletteData &paletteData) {
_palette = paletteData;
}
CBofPalette::~CBofPalette() {
assert(isValidObject(this));
// If we trash the games palette, then reset it back to nullptr.
CBofApp *pApp = CBofApp::getApp();
if (pApp != nullptr) {
if (this == pApp->getPalette()) {
pApp->setPalette(nullptr);
}
}
ReleasePalette();
}
void CBofPalette::setPalette(const PaletteData &PaletteData) {
assert(isValidObject(this));
ReleasePalette();
_palette = PaletteData;
}
ErrorCode CBofPalette::loadPalette(const char *pszFileName, uint16 nFlags) {
assert(isValidObject(this));
// Validate input
assert(pszFileName != nullptr);
ReleasePalette();
// Load in new bitmap file to get the palette
Common::File f;
Image::BitmapDecoder decoder;
if (f.open(pszFileName) && decoder.loadStream(f)) {
// Copy the palette
const Graphics::Palette &pal = decoder.getPalette();
_palette._numColors = pal.size();
pal.grab(_palette._data, 0, pal.size());
_errCode = ERR_NONE;
} else {
_errCode = ERR_FREAD;
}
return _errCode;
}
void CBofPalette::ReleasePalette() {
Common::fill(_palette._data, _palette._data + Graphics::PALETTE_SIZE, 0);
}
CBofPalette *CBofPalette::copyPalette() {
assert(isValidObject(this));
return nullptr;
}
byte CBofPalette::getNearestIndex(COLORREF stRGB) {
Graphics::PaletteLookup lookup(_palette._data, Graphics::PALETTE_COUNT);
return lookup.findBestColor(GetRed(stRGB), GetGreen(stRGB), GetBlue(stRGB));
}
COLORREF CBofPalette::getColor(byte nIndex) {
const byte *rgb = &_palette._data[nIndex * 3];
COLORREF cColor = RGB(rgb[0], rgb[1], rgb[2]);
return cColor;
}
ErrorCode CBofPalette::createDefault(uint16 nFlags) {
assert(isValidObject(this));
byte *pal = _palette._data;
for (int i = 0; i < 256; ++i, pal += 3)
pal[0] = pal[1] = pal[2] = (byte)i;
return ERR_NONE;
}
ErrorCode CBofPalette::setSharedPalette(const char *pszFileName) {
delete _pSharedPalette;
_pSharedPalette = nullptr;
// Save name of file used to get the shared palette
if (pszFileName != nullptr) {
Common::strcpy_s(_szSharedPalFile, pszFileName);
}
return ERR_NONE;
}
CBofPalette *CBofPalette::getSharedPalette() {
// Do we need to load the shared palette?
if (_pSharedPalette == nullptr && fileExists(_szSharedPalFile))
_pSharedPalette = new CBofPalette(_szSharedPalFile);
return _pSharedPalette;
}
} // namespace SpaceBar
} // namespace Bagel

View File

@@ -0,0 +1,153 @@
/* 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_GFX_PALETTE_H
#define BAGEL_BOFLIB_GFX_PALETTE_H
#include "graphics/palette.h"
#include "bagel/afxwin.h"
#include "bagel/boflib/error.h"
#include "bagel/boflib/object.h"
#include "bagel/boflib/stdinc.h"
namespace Bagel {
namespace SpaceBar {
struct PaletteData {
byte _data[Graphics::PALETTE_SIZE];
int16 _numColors;
PaletteData(int16 numColors = Graphics::PALETTE_COUNT);
};
struct PALETTEENTRY {
byte peRed;
byte peGreen;
byte peBlue;
byte peFlags;
};
struct LOGPALETTE {
int16 palNumEntries;
int16 palVersion;
PALETTEENTRY palPalEntry[1];
};
struct BOFRGBQUAD {
byte rgbBlue;
byte rgbGreen;
byte rgbRed;
byte rgbReserved;
};
#define GetRed(rgb) ((byte)((rgb) & 0x000000FF))
#define GetGreen(rgb) ((byte)(((rgb) >> 8) & 0x000000FF))
#define GetBlue(rgb) ((byte)(((rgb) >> 16) & 0x000000FF))
class CBofPalette : public CBofError, public CBofObject {
protected:
PaletteData _palette;
static CBofPalette *_pSharedPalette;
static char _szSharedPalFile[MAX_FNAME];
/**
* Deletes internal palette info
*/
void ReleasePalette();
public:
/**
* Default constructor
*/
CBofPalette();
/**
* Constructor that loads a palette from a file
* @param pszFileName filename
*/
CBofPalette(const char *pszFileName);
/**
* Constructor that takes in an existing palette
*/
CBofPalette(const PaletteData &paletteData);
/**
* Loads palette from specified bitmap-file
* @param pszFileName Name of file to load palette from
* @param nFlags Flags for animation, etc...
* @return Error return Code
*/
ErrorCode loadPalette(const char *pszFileName, uint16 nFlags = PAL_DEFAULT);
ErrorCode createDefault(uint16 nFlags = PAL_DEFAULT);
byte getNearestIndex(COLORREF cColor);
COLORREF getColor(byte nIndex);
/**
* Assigns specified palette to this CBofPalette
* @param PaletteData Handle to windows palette
*/
void setPalette(const PaletteData &PaletteData);
const PaletteData &getPalette() const {
return _palette;
}
const byte *getData() const {
return _palette._data;
}
void setData(const byte* colors) {
memcpy(_palette._data, colors, Graphics::PALETTE_SIZE);
}
virtual ~CBofPalette();
/**
* Create a new palette based on current palette
*/
CBofPalette *copyPalette();
/**
* initialize static class fields
*/
static void initialize();
/**
* Called only in response to "SHAREDPAL=filename" in a script file
* @param pszFileName Palette filename
*/
static ErrorCode setSharedPalette(const char *pszFileName);
/**
* Returns the current shared palette
* @return Pointer to shared palette
*/
static CBofPalette *getSharedPalette();
};
} // namespace SpaceBar
} // namespace Bagel
#endif

View File

@@ -0,0 +1,254 @@
/* 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_POINT_H
#define BAGEL_BOFLIB_POINT_H
#include "bagel/afxwin.h"
#include "bagel/boflib/stdinc.h"
#include "bagel/boflib/object.h"
namespace Bagel {
class CBofPoint : public StPoint, public CBofObject {
public:
// Constructors
CBofPoint();
CBofPoint(int initX, int initY);
CBofPoint(StPoint stPoint);
CBofPoint(const CBofPoint &cPoint);
CBofPoint(const StSize &stSize);
CBofPoint(const Common::Point &pt);
CBofPoint(const POINT &stPoint) {
setWinPoint(&stPoint);
}
virtual ~CBofPoint() {
}
void setWinPoint(const POINT *pPoint);
POINT GetWinPoint() const;
void operator=(const POINT &stPoint) {
setWinPoint(&stPoint);
}
operator const POINT() {
return GetWinPoint();
}
// Operations
void offset(int xOffset, int yOffset);
void offset(StPoint point);
void offset(StSize size);
void operator=(const StPoint &point);
void operator=(const CBofPoint &point);
bool operator==(StPoint point) const;
bool operator!=(StPoint point) const;
void operator+=(StSize size);
void operator-=(StSize size);
void operator+=(StPoint point);
void operator-=(StPoint point);
// Operators returning CBofPoint values
CBofPoint operator+(StSize size) const;
CBofPoint operator+(StPoint point) const;
CBofPoint operator-(StSize size) const;
CBofPoint operator-(StPoint point) const;
CBofPoint operator-() const;
};
// CBofPoint
inline CBofPoint::CBofPoint() {
x = 0;
y = 0;
}
inline CBofPoint::CBofPoint(const int initX, const int initY) {
x = initX;
y = initY;
}
inline CBofPoint::CBofPoint(const StPoint stPoint) {
x = stPoint.x;
y = stPoint.y;
}
inline CBofPoint::CBofPoint(const StSize &stSize) {
x = stSize.cx;
y = stSize.cy;
}
inline CBofPoint::CBofPoint(const CBofPoint &cPoint) {
x = cPoint.x;
y = cPoint.y;
}
inline CBofPoint::CBofPoint(const Common::Point &pt) {
x = pt.x;
y = pt.y;
}
inline void CBofPoint::setWinPoint(const POINT *pPoint) {
assert(pPoint != nullptr);
assert(isValidObject(this));
x = pPoint->x;
y = pPoint->y;
}
inline POINT CBofPoint::GetWinPoint() const {
assert(isValidObject(this));
POINT stPoint;
stPoint.x = x;
stPoint.y = y;
return stPoint;
}
inline void CBofPoint::offset(int xOffset, int yOffset) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x += xOffset;
y += yOffset;
}
inline void CBofPoint::offset(StPoint point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x += point.x;
y += point.y;
}
inline void CBofPoint::offset(StSize size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x += size.cx;
y += size.cy;
}
inline void CBofPoint::operator=(const StPoint &point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x = point.x;
y = point.y;
}
inline void CBofPoint::operator=(const CBofPoint &point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x = point.x;
y = point.y;
}
inline bool CBofPoint::operator==(StPoint point) const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (x == point.x && y == point.y);
}
inline bool CBofPoint::operator!=(StPoint point) const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (x != point.x || y != point.y);
}
inline void CBofPoint::operator+=(StSize size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x += size.cx;
y += size.cy;
}
inline void CBofPoint::operator+=(StPoint point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x += point.x;
y += point.y;
}
inline void CBofPoint::operator-=(StPoint point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x -= point.x;
y -= point.y;
}
inline void CBofPoint::operator-=(StSize size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
x -= size.cx;
y -= size.cy;
}
inline CBofPoint CBofPoint::operator+(StSize size) const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(x + size.cx, y + size.cy);
}
inline CBofPoint CBofPoint::operator+(StPoint point) const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(x + point.x, y + point.y);
}
inline CBofPoint CBofPoint::operator-(StSize size) const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(x - size.cx, y - size.cy);
}
inline CBofPoint CBofPoint::operator-(StPoint point) const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(x - point.x, y - point.y);
}
inline CBofPoint CBofPoint::operator-() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(-x, -y);
}
} // namespace Bagel
#endif

View File

@@ -0,0 +1,113 @@
/* 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/boflib/queue.h"
#include "bagel/boflib/stdinc.h"
namespace Bagel {
CQueue::CQueue() {
}
CQueue::~CQueue() {
// Can't destruct if we don't exist
assert(isValidObject(this));
while (removeItem() != nullptr) {
}
// remove() must set _pQueueList to nullptr when it removes the last item
assert(_pQueueList == nullptr);
}
void CQueue::addItem(void *pObject) {
// Make sure this object exists
assert(isValidObject(this));
CLList *pNewItem = new CLList(pObject);
if (_pQueueList != nullptr) {
_pQueueList->addToTail(pNewItem);
} else {
_pQueueList = pNewItem;
}
assert(pNewItem->getHead() == _pQueueList);
}
void *CQueue::removeItem() {
// Make sure this object exists
assert(isValidObject(this));
// Assume empty list
void *pObject = nullptr;
CLList *pList = _pQueueList;
if (pList != nullptr) {
pObject = pList->getData();
_pQueueList = pList->getNext();
delete pList;
}
return pObject;
}
void CQueue::deleteItem(void *pItem) {
// Make sure this object exists
assert(isValidObject(this));
assert(pItem != nullptr);
CLList *pList = _pQueueList;
while (pList != nullptr) {
CLList *pNext = pList->getNext();
if (pItem == pList->getData()) {
// If this is the 1st item in the Queue, then move head
if (pList == _pQueueList)
_pQueueList = _pQueueList->getNext();
delete pList;
break;
}
pList = pNext;
}
}
void *CQueue::getQItem() {
assert(isValidObject(this));
void *pItem = nullptr;
if (_pQueueList != nullptr) {
pItem = _pQueueList->getData();
}
return pItem;
}
void CQueue::flush() {
assert(isValidObject(this));
while (removeItem() != nullptr) {
}
}
} // namespace Bagel

View File

@@ -0,0 +1,78 @@
/* 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_QUEUE_H
#define BAGEL_BOFLIB_QUEUE_H
#include "bagel/boflib/object.h"
#include "bagel/boflib/llist.h"
namespace Bagel {
class CQueue : public CBofObject {
protected:
CLList *_pQueueList = nullptr;
public:
/**
* Default constructor
*/
CQueue();
/**
* Destructor
*/
virtual ~CQueue();
/**
* Pushes object onto stack
* @param pObject Pointer to object to be pushed
*/
void addItem(void *pObject);
/**
* Removes 1 object off stack
* @return Pointer to top object on stack
*/
void *removeItem();
/**
* Retrieves the 1st item (FIFO order) without removing it.
* @return 1st item in Queue (or nullptr is Queue is empty)
*/
void *getQItem();
/**
* Deletes specified item from the QUEUE (Illegally)
* @param pObject Object to remove
*/
void deleteItem(void *pObject);
/**
* Removes all items from the queue
*/
void flush();
};
} // namespace Bagel
#endif

455
engines/bagel/boflib/rect.h Normal file
View File

@@ -0,0 +1,455 @@
/* 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_RECT_H
#define BAGEL_BOFLIB_RECT_H
#include "common/rect.h"
#include "bagel/afxwin.h"
#include "bagel/boflib/stdinc.h"
#include "bagel/boflib/object.h"
#include "bagel/boflib/point.h"
#include "bagel/boflib/size.h"
namespace Bagel {
class CBofRect : public CBofObject {
public:
// Constructors
CBofRect();
CBofRect(int l, int t, int r, int b);
CBofRect(const CBofRect &srcRect);
CBofRect(const CBofPoint &point, const CBofSize &size);
CBofRect(const CBofPoint &pttopLeft, const CBofPoint &ptBottomRight);
virtual ~CBofRect() {
}
// Attributes
int width() const;
int height() const;
CBofSize size() const;
CBofPoint topLeft() const;
CBofPoint bottomRight() const;
CBofPoint topRight() const;
CBofPoint bottomLeft() const;
bool isRectEmpty() const;
bool isRectNull() const;
bool ptInRect(const CBofPoint &point) const;
// Operations
inline void setRect(int x1, int y1, int x2, int y2);
void setRectEmpty();
void copyRect(const CBofRect &cRect);
bool equalRect(const CBofRect &cRect);
CBofRect(const RECT &cRect) {
setWinRect(&cRect);
}
CBofRect(const RECT *pRect) {
setWinRect(pRect);
}
void setWinRect(const RECT *pRect);
RECT getWinRect();
void operator=(const RECT &srcRect) {
setWinRect(&srcRect);
}
void operator=(const Common::Rect &srcRect) {
const RECT r = { srcRect.left, srcRect.top, srcRect.right, srcRect.bottom };
setWinRect(&r);
}
operator const RECT() {
return getWinRect();
}
operator const Common::Rect() {
return Common::Rect(left, top, right, bottom);
}
void offsetRect(int x, int y);
void offsetRect(const CBofSize &size);
void offsetRect(const CBofPoint &point);
// Operations that fill '*this' with result
bool intersectRect(const CBofRect *pRect1, const CBofRect *pRect2);
bool intersectRect(const CBofRect &cRect1, const CBofRect &cRect2);
bool unionRect(const CBofRect *pRect1, const CBofRect *pRect2);
// Additional Operations
void operator=(const CBofRect &srcRect);
bool operator==(const CBofRect &rect);
bool operator!=(const CBofRect &rect);
void operator+=(const CBofPoint &point);
void operator-=(const CBofPoint &point);
void operator&=(const CBofRect &rect);
void operator|=(const CBofRect &rect);
// Operators returning CBofRect values
CBofRect operator+(const CBofPoint &point);
CBofRect operator-(const CBofPoint &point);
CBofRect operator&(const CBofRect &rect2);
CBofRect operator|(const CBofRect &rect2);
int left;
int top;
int right;
int bottom;
};
inline CBofRect::CBofRect() {
top = left = 0;
right = bottom = -1;
}
inline CBofRect::CBofRect(int l, int t, int r, int b) {
left = l;
top = t;
right = r;
bottom = b;
}
inline CBofRect::CBofRect(const CBofRect &srcRect) {
left = srcRect.left;
top = srcRect.top;
right = srcRect.right;
bottom = srcRect.bottom;
}
inline CBofRect::CBofRect(const CBofPoint &point, const CBofSize &size) {
right = (left = point.x) + size.cx - 1;
bottom = (top = point.y) + size.cy - 1;
}
inline CBofRect::CBofRect(const CBofPoint &pttopLeft, const CBofPoint &ptBottomRight) {
setRect(pttopLeft.x, pttopLeft.y, ptBottomRight.x, ptBottomRight.y);
}
inline int CBofRect::width() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return right - left + 1;
}
inline int CBofRect::height() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return bottom - top + 1;
}
inline CBofSize CBofRect::size() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofSize(width(), height());
}
inline CBofPoint CBofRect::topLeft() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(left, top);
}
inline CBofPoint CBofRect::bottomRight() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(right, bottom);
}
inline CBofPoint CBofRect::topRight() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(right, top);
}
inline CBofPoint CBofRect::bottomLeft() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofPoint(left, bottom);
}
inline bool CBofRect::isRectEmpty() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (width() <= 0 || height() <= 0);
}
inline bool CBofRect::isRectNull() const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (left == 0 && right == 0 && top == 0 && bottom == 0);
}
inline bool CBofRect::ptInRect(const CBofPoint &point) const {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (point.x >= left && point.x <= right && point.y >= top && point.y <= bottom);
}
inline void CBofRect::setRect(int x1, int y1, int x2, int y2) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
left = x1;
top = y1;
right = x2;
bottom = y2;
}
inline void CBofRect::setRectEmpty() {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
left = top = 0;
right = bottom = -1;
// Verify that the rectangle is now empty
assert(isRectEmpty());
}
inline void CBofRect::copyRect(const CBofRect &cSrcRect) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
assert(isValidObject(&cSrcRect));
left = cSrcRect.left;
right = cSrcRect.right;
top = cSrcRect.top;
bottom = cSrcRect.bottom;
}
inline bool CBofRect::equalRect(const CBofRect &cRect) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
assert(isValidObject(&cRect));
return (left == cRect.left && right == cRect.right && top == cRect.top && bottom == cRect.bottom);
}
inline RECT CBofRect::getWinRect() {
assert(isValidObject(this));
RECT stRect;
stRect.left = left;
stRect.top = top;
stRect.right = right + 1;
stRect.bottom = bottom + 1;
return stRect;
}
inline void CBofRect::setWinRect(const RECT *pRect) {
assert(isValidObject(this));
assert(pRect != nullptr);
left = pRect->left;
top = pRect->top;
right = pRect->right - 1;
bottom = pRect->bottom - 1;
}
inline void CBofRect::offsetRect(int x, int y) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
left += x;
right += x;
top += y;
bottom += y;
}
inline void CBofRect::offsetRect(const CBofPoint &point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
left += point.x;
right += point.x;
top += point.y;
bottom += point.y;
}
inline void CBofRect::offsetRect(const CBofSize &size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
left += size.cx;
right += size.cx;
top += size.cy;
bottom += size.cy;
}
inline bool CBofRect::intersectRect(const CBofRect *pRect1, const CBofRect *pRect2) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
// Can't access null pointers
assert(pRect1 != nullptr);
assert(pRect2 != nullptr);
left = MAX(pRect1->left, pRect2->left);
top = MAX(pRect1->top, pRect2->top);
right = MIN(pRect1->right, pRect2->right);
bottom = MIN(pRect1->bottom, pRect2->bottom);
return ((width() > 0) && (height() > 0));
}
inline bool CBofRect::intersectRect(const CBofRect &cRect1, const CBofRect &cRect2) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return intersectRect(&cRect1, &cRect2);
}
inline bool CBofRect::unionRect(const CBofRect *pRect1, const CBofRect *pRect2) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
// Can't access null pointers
assert(pRect1 != nullptr);
assert(pRect2 != nullptr);
left = MIN(pRect1->left, pRect2->left);
top = MIN(pRect1->top, pRect2->top);
right = MAX(pRect1->right, pRect2->right);
bottom = MAX(pRect1->bottom, pRect2->bottom);
return isRectEmpty();
}
inline void CBofRect::operator=(const CBofRect &srcRect) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
left = srcRect.left;
right = srcRect.right;
top = srcRect.top;
bottom = srcRect.bottom;
}
inline bool CBofRect::operator==(const CBofRect &rect) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (left == rect.left && right == rect.right &&
top == rect.top && bottom == rect.bottom);
}
inline bool CBofRect::operator!=(const CBofRect &rect) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (left != rect.left || right != rect.right ||
top != rect.top || bottom != rect.bottom);
}
inline void CBofRect::operator+=(const CBofPoint &point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
offsetRect(point);
}
inline void CBofRect::operator-=(const CBofPoint &point) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
offsetRect(-point.x, -point.y);
}
inline void CBofRect::operator&=(const CBofRect &rect) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
intersectRect(this, &rect);
}
inline void CBofRect::operator|=(const CBofRect &rect) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
unionRect(this, &rect);
}
inline CBofRect CBofRect::operator+(const CBofPoint &pt) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
CBofRect rect(*this);
rect.offsetRect(pt.x, pt.y);
return rect;
}
inline CBofRect CBofRect::operator-(const CBofPoint &pt) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
CBofRect rect(*this);
rect.offsetRect(-pt.x, -pt.y);
return rect;
}
inline CBofRect CBofRect::operator&(const CBofRect &rect2) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
CBofRect rect;
rect.intersectRect(this, &rect2);
return rect;
}
inline CBofRect CBofRect::operator|(const CBofRect &rect2) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
CBofRect rect;
rect.unionRect(this, &rect2);
return rect;
}
} // namespace Bagel
#endif

139
engines/bagel/boflib/size.h Normal file
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_BOFLIB_SIZE_H
#define BAGEL_BOFLIB_SIZE_H
#include "bagel/afxwin.h"
#include "bagel/boflib/stdinc.h"
#include "bagel/boflib/object.h"
namespace Bagel {
class CBofSize : public SIZE, public CBofObject {
public:
// Constructors
CBofSize();
virtual ~CBofSize() {
}
CBofSize(int initCX, int initCY);
CBofSize(const SIZE &stSize);
CBofSize(const CBofSize &cSize);
CBofSize(StPoint stPoint);
// Operations
void operator=(const CBofSize &cSize);
bool operator==(SIZE size);
bool operator!=(SIZE size);
void operator+=(SIZE size);
void operator-=(SIZE size);
// Operators returning CBofSize values
CBofSize operator+(SIZE size);
CBofSize operator-(SIZE size);
CBofSize operator-();
};
// CBofSize
inline CBofSize::CBofSize() {
cx = cy = 0;
}
inline CBofSize::CBofSize(int initCX, int initCY) {
cx = initCX;
cy = initCY;
}
inline CBofSize::CBofSize(const SIZE &stSize) {
cx = stSize.cx;
cy = stSize.cy;
}
inline CBofSize::CBofSize(const CBofSize &cSize) {
cx = cSize.cx;
cy = cSize.cy;
}
inline CBofSize::CBofSize(StPoint stPoint) {
cx = stPoint.x;
cy = stPoint.y;
}
inline void CBofSize::operator=(const CBofSize &cSize) {
cx = cSize.cx;
cy = cSize.cy;
}
inline bool CBofSize::operator==(SIZE size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (cx == size.cx && cy == size.cy);
}
inline bool CBofSize::operator!=(SIZE size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return (cx != size.cx || cy != size.cy);
}
inline void CBofSize::operator+=(SIZE size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
cx += size.cx;
cy += size.cy;
}
inline void CBofSize::operator-=(SIZE size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
cx -= size.cx;
cy -= size.cy;
}
inline CBofSize CBofSize::operator+(SIZE size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofSize(cx + size.cx, cy + size.cy);
}
inline CBofSize CBofSize::operator-(SIZE size) {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofSize(cx - size.cx, cy - size.cy);
}
inline CBofSize CBofSize::operator-() {
// Make sure object is not used after it is destructed
assert(isValidObject(this));
return CBofSize(-cx, -cy);
}
} // namespace Bagel
#endif

View File

@@ -0,0 +1,959 @@
/* 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/system.h"
#include "common/file.h"
#include "common/memstream.h"
#include "audio/mixer.h"
#include "audio/audiostream.h"
#include "audio/decoders/wave.h"
#include "bagel/bagel.h"
#include "bagel/boflib/sound.h"
#include "bagel/boflib/string_functions.h"
#include "bagel/boflib/event_loop.h"
#include "bagel/boflib/file_functions.h"
#include "bagel/boflib/log.h"
#include "bagel/music.h"
//#include "bagel/spacebar/boflib/app.h"
namespace Bagel {
#define MEMORY_THRESHOLD 20000L
#define MEMORY_MARGIN 100000L
char CBofSound::_szDrivePath[MAX_DIRPATH];
CBofSound *CBofSound::_pSoundChain = nullptr; // Pointer to chain of linked Sounds
int CBofSound::_nCount = 0; // Count of currently active Sounds
int CBofSound::_nWavCount = 1; // Available wave sound devices
int CBofSound::_nMidiCount = 1; // Available midi sound devices
void *CBofSound::_pMainWnd = nullptr; // Window for message processing
bool CBofSound::_bInit = false;
CQueue *CBofSound::_cQueue[NUM_QUEUES];
int CBofSound::_nSlotVol[NUM_QUEUES];
CBofSound::CBofSound() {
_wLoops = 1;
addToSoundChain();
}
CBofSound::CBofSound(void *pWnd, const char *pszPathName, uint16 wFlags, const int nLoops) {
_wLoops = (uint16)nLoops;
initialize(pWnd, pszPathName, wFlags);
addToSoundChain();
}
void CBofSound::addToSoundChain() {
// Insert this sound into the sound list
if (_pSoundChain != nullptr) {
_pSoundChain->Insert(this);
// _pSoundchain must always be the head of the list
assert(_pSoundChain == _pSoundChain->getHead());
} else {
_pSoundChain = this;
}
}
void CBofSound::initialize(void *pWnd, const char *pszPathName, uint16 wFlags) {
// Validate input
assert(pszPathName != nullptr);
assert(strlen(pszPathName) < MAX_FNAME);
//
// Initialize data fields
//
_pWnd = _pMainWnd;
if (pWnd != nullptr) {
_pWnd = pWnd;
if (_pMainWnd == nullptr)
_pMainWnd = pWnd;
}
_bPlaying = false; // Not yet playing
_bStarted = false;
_wFlags = wFlags; // Flags for playing
_bPaused = false; // Not suspended
_bExtensionsUsed = false; // No extended flags used.
_szFileName[0] = '\0';
_handle = {};
_pFileBuf = nullptr;
_nVol = VOLUME_INDEX_DEFAULT;
_bInQueue = false;
_iQSlot = 0;
for (int i = 0; i < NUM_QUEUES; i++) {
_nSlotVol[i] = VOLUME_INDEX_DEFAULT;
}
// Mixed assumes Asynchronous
if ((_wFlags & SOUND_MIX) == SOUND_MIX) {
_wFlags |= SOUND_ASYNCH;
}
if (_wFlags & SOUND_MIDI) {
_chType = g_engine->isSpaceBar() ?
SOUND_TYPE_XM : SOUND_TYPE_SMF;
} else {
_chType = SOUND_TYPE_WAV;
}
if (pszPathName != nullptr && (_wFlags & SND_MEMORY)) {
// In-memory wave sound
_pFileBuf = (byte *)const_cast<char *>(pszPathName);
_iFileSize = 999999;
} else if (pszPathName != nullptr) {
if ((_szDrivePath[0] != '\0') && (*pszPathName == '.'))
pszPathName++;
else if (!strncmp(pszPathName, ".\\", 2))
pszPathName += 2;
char szTempPath[MAX_DIRPATH];
snprintf(szTempPath, MAX_DIRPATH, "%s%s", _szDrivePath, pszPathName);
strreplaceStr(szTempPath, "\\\\", "\\");
strreplaceStr(szTempPath, "\\", "/");
// Continue as long as this file exists
if (fileExists(szTempPath)) {
fileGetFullPath(_szFileName, szTempPath);
if (!(_wFlags & SOUND_QUEUE)) {
if (_wFlags & SOUND_WAVE || _wFlags & SOUND_MIX) {
loadSound();
}
}
} else if (_wFlags & SOUND_MIDI) {
// Try both MIDI formats
strreplaceStr(szTempPath, ".MID", ".MOV");
if (fileExists(szTempPath)) {
fileGetFullPath(_szFileName, szTempPath);
_chType = SOUND_TYPE_QT;
} else {
reportError(ERR_FFIND, szTempPath);
}
} else {
reportError(ERR_FFIND, szTempPath);
}
}
}
CBofSound::~CBofSound() {
assert(isValidObject(this));
stop();
releaseSound();
if (this == _pSoundChain) { // special case head of chain
_pSoundChain = (CBofSound *)_pSoundChain->getNext();
}
}
void CBofSound::initialize() {
for (int i = 0; i < NUM_QUEUES; ++i)
_cQueue[i] = new CQueue();
resetQVolumes();
}
void CBofSound::resetQVolumes() {
// Set Q Volumes to default
for (int i = 0; i < NUM_QUEUES; i++) {
_nSlotVol[i] = VOLUME_INDEX_DEFAULT;
}
}
void CBofSound::shutdown() {
// Auto-delete any remaining sounds
clearSounds();
for (int i = 0; i < NUM_QUEUES; ++i)
delete _cQueue[i];
}
void CBofSound::setVolume(int nVolume) {
assert(nVolume >= VOLUME_INDEX_MIN && nVolume <= VOLUME_INDEX_MAX);
_nVol = CLIP(nVolume, VOLUME_INDEX_MIN, VOLUME_INDEX_MAX);
Audio::Mixer *mixer = g_system->getMixer();
byte vol = VOLUME_SVM(_nVol);
mixer->setChannelVolume(_handle, vol);
mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol);
mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol);
g_engine->_midi->setVolume(vol);
}
void CBofSound::setVolume(int nMidiVolume, int nWaveVolume) {
assert(nMidiVolume >= VOLUME_INDEX_MIN && nMidiVolume <= VOLUME_INDEX_MAX);
assert(nWaveVolume >= VOLUME_INDEX_MIN && nWaveVolume <= VOLUME_INDEX_MAX);
// Set master wave volume
int clippedVol = CLIP(nWaveVolume, VOLUME_INDEX_MIN, VOLUME_INDEX_MAX);
g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, VOLUME_SVM(clippedVol));
// Set master Midi volume
clippedVol = CLIP(nMidiVolume, VOLUME_INDEX_MIN, VOLUME_INDEX_MAX);
g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, VOLUME_SVM(clippedVol));
g_engine->_midi->setVolume(VOLUME_SVM(clippedVol));
}
bool CBofSound::play(uint32 dwBeginHere, uint32 TimeFormatFlag) {
assert(isValidObject(this));
// Assume success
bool bSuccess = true;
if (_errCode == ERR_NONE) {
// We must be attached to a valid window
assert((_pWnd != nullptr) || (_pMainWnd != nullptr));
// If already playing, then stop and start again
if (playing()) {
// Can't replay an autodelete sound
assert(!(_wFlags & SOUND_AUTODELETE));
stop();
}
// WAVE and MIX are mutually exclusive
assert(!((_wFlags & SOUND_WAVE) && (_wFlags & SOUND_MIX)));
if (_wFlags & SOUND_WAVE) {
if (_wFlags & SOUND_QUEUE)
waitWaveSounds();
else
stopWaveSounds();
} else if (_wFlags & SOUND_MIDI) {
if (_wFlags & SOUND_QUEUE)
waitMidiSounds();
else
stopMidiSounds();
}
// Make sure this sound is still valid
assert(_pSoundChain != nullptr);
if (_pFileBuf == nullptr) {
if ((_wFlags & (SOUND_MIX | SOUND_QUEUE)) == (SOUND_MIX | SOUND_QUEUE)) {
// Don't pre-load it
} else {
loadSound();
}
}
if (_wFlags & SOUND_MIDI) {
if (_wFlags & SOUND_LOOP)
_wLoops = 0;
g_engine->_midi->play(this);
_bPlaying = true;
} else if (_wFlags & SOUND_WAVE) {
playWAV();
if (_bPlaying) {
if (!(_wFlags & SOUND_ASYNCH)) {
EventLoop eventLoop;
auto *mixer = g_system->getMixer();
while (mixer->isSoundHandleActive(_handle)) {
if (eventLoop.frame()) {
stop();
break;
}
}
_handle = {};
_bPlaying = false;
}
}
} else if (_wFlags & SOUND_MIX) {
if (!(_wFlags & SOUND_QUEUE)) {
playWAV();
} else {
assert(_iQSlot >= 0 && _iQSlot < NUM_QUEUES);
_cQueue[_iQSlot]->addItem(this);
_bPlaying = true;
_bInQueue = true;
setVolume(_nSlotVol[_iQSlot]);
}
}
}
return bSuccess;
}
bool CBofSound::midiLoopPlaySegment(uint32 dwLoopFrom, uint32 dwLoopTo, uint32 dwBegin, uint32 TimeFmt) {
assert(isValidObject(this));
_wFlags |= SOUND_LOOP;
_wLoops = 0;
_dwRePlayStart = dwLoopFrom;
_dwRePlayEnd = dwLoopTo;
_bExtensionsUsed = true;
bool bSuccess = play(dwBegin, TimeFmt);
return bSuccess;
}
bool CBofSound::pauseSounds() {
bool bSuccess = true;
// Thumb through all the sounds
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
// If one is playing and not paused try to suspend it
if (pSound->playing() && (pSound->_bPaused == false)) {
bool bStatus = pSound->pause();
if (bStatus)
pSound->_bPaused = true;
else
bSuccess = false;
}
pSound = (CBofSound *)pSound->getNext();
}
return bSuccess;
}
bool CBofSound::pause() {
assert(isValidObject(this));
bool bSuccess = false;
// Must be playing to be paused and not already paused
if (playing() && (_bPaused == false)) {
bSuccess = true;
if (_wFlags & SOUND_MIDI) {
g_engine->_midi->pause();
} else {
g_system->getMixer()->pauseHandle(_handle, true);
}
}
if (bSuccess)
_bPaused = true;
return bSuccess;
}
bool CBofSound::resumeSounds() {
bool bSuccess = true;
CBofSound *pSound = _pSoundChain; // Thumb through all the sounds
while (pSound != nullptr) {
if (pSound->_bPaused) {
// If one is paused
bool bStatus = pSound->resume(); // ... try to get it going again
if (bStatus)
pSound->_bPaused = false; // success
else
bSuccess = false; // failure
}
pSound = (CBofSound *)pSound->getNext();
}
return bSuccess;
}
bool CBofSound::resume() {
assert(isValidObject(this));
bool bSuccess = false;
if (_bPaused) { // must be paused to resume
bSuccess = true;
if (_wFlags & SOUND_MIDI) {
g_engine->_midi->resume();
} else {
g_system->getMixer()->pauseHandle(_handle, false);
}
}
if (bSuccess)
_bPaused = false;
return bSuccess;
}
void CBofSound::stopSounds() {
CBofSound *pSound = _pSoundChain; // Thumb through all the sounds
while (pSound != nullptr) {
if (pSound->playing()) { // If one is playing
pSound->_bPaused = false; // ... its no longer paused
pSound->stop(); // Stop it
}
pSound = (CBofSound *)pSound->getNext();
}
}
void CBofSound::stopWaveSounds() {
CBofSound *pSound = _pSoundChain; // Find this Sound is the queue
while (pSound != nullptr) {
CBofSound *pNextSound = (CBofSound *)pSound->getNext();
if (pSound->playing() && ((pSound->_wFlags & SOUND_WAVE) || (pSound->_wFlags & SOUND_MIX))) {
pSound->stop();
if (pSound->_wFlags & SOUND_AUTODELETE)
delete pSound;
}
pSound = pNextSound;
}
}
void CBofSound::stopMidiSounds() {
CBofSound *pSound = _pSoundChain; // Find this Sound is the queue
while (pSound != nullptr) {
CBofSound *pNextSound = (CBofSound *)pSound->getNext();
if (pSound->playing() && (pSound->_wFlags & SOUND_MIDI)) {
pSound->stop();
if (pSound->_wFlags & SOUND_AUTODELETE)
delete pSound;
}
pSound = pNextSound;
}
}
void CBofSound::stop() {
assert(isValidObject(this));
// If this sound is currently playing
if (_wFlags & SOUND_MIDI) {
g_engine->_midi->stop();
} else {
g_system->getMixer()->stopHandle(_handle);
_handle = {};
}
if (_bInQueue) {
assert(_iQSlot >= 0 && _iQSlot < NUM_QUEUES);
_cQueue[_iQSlot]->deleteItem(this);
_bInQueue = false;
}
_bPlaying = false;
_bStarted = false;
_bPaused = false;
// One less audio playing
_nCount -= 1;
}
void CBofSound::clearSounds() {
stopSounds(); // Stop all active sounds
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) { // Delete all sound entries
CBofSound *pNextSound = pSound->getNext();
delete pSound;
pSound = pNextSound;
}
assert(_pSoundChain == nullptr);
}
void CBofSound::clearWaveSounds() {
CBofSound *pSound = _pSoundChain; // Find this Sound in the queue
while (pSound != nullptr) {
CBofSound *pNextSound = pSound->getNext();
if ((pSound->_wFlags & SOUND_WAVE) || (pSound->_wFlags & SOUND_MIX))
delete pSound;
pSound = pNextSound;
}
}
void CBofSound::clearMidiSounds() {
CBofSound *pSound = _pSoundChain; // find this Sound is the queue
while (pSound != nullptr) {
CBofSound *pNextSound = (CBofSound *)pSound->getNext();
if (pSound->_wFlags & SOUND_MIDI)
delete pSound;
pSound = pNextSound;
}
}
void CBofSound::waitSounds() {
waitWaveSounds();
waitMidiSounds();
}
void CBofSound::waitWaveSounds() {
uint32 dwTickCount = 0;
for (;;) {
audioTask();
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (pSound->playing() && (pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX)) {
break;
}
pSound = (CBofSound *)pSound->getNext();
}
if (pSound == nullptr)
break;
if (handleMessages())
break;
// If 3 minutes go by, then just bolt
if (dwTickCount == 0)
dwTickCount = g_system->getMillis() + 1000 * 60 * 3;
if (g_system->getMillis() > dwTickCount) {
pSound->stop();
pSound->_bPlaying = false;
pSound->reportError(ERR_UNKNOWN, "CBofSound::waitWaveSounds() timeout!");
}
}
}
bool CBofSound::soundsPlaying() {
audioTask();
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (pSound->playing() && (pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX)) {
return true;
}
pSound = (CBofSound *)pSound->getNext();
}
return false;
}
void CBofSound::waitMidiSounds() {
uint32 dwTickCount = 0;
for (;;) {
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (pSound->playing() && (pSound->_wFlags & SOUND_MIDI)) {
break;
}
pSound = (CBofSound *)pSound->getNext();
}
if (pSound == nullptr)
break;
if (handleMessages())
break;
if (dwTickCount == 0)
dwTickCount = g_system->getMillis() + 1000 * 60;
if (g_system->getMillis() > dwTickCount) {
pSound->stop();
pSound->reportError(ERR_UNKNOWN, "CBofSound::waitMidiSounds() timeout");
break;
}
}
}
bool CBofSound::handleMessages() {
if (g_engine->isSpaceBar()) {
Common::Event e;
while (g_system->getEventManager()->pollEvent(e)) {
}
g_system->delayMillis(10);
} else {
AfxGetApp()->pause();
}
return g_engine->shouldQuit();
}
bool CBofSound::bofSleep(uint32 wait) {
uint32 goal = wait + g_system->getMillis();
while (goal > g_system->getMillis()) {
if (handleMessages())
return true;
}
return false;
}
bool BofPlaySound(const char *pszSoundFile, uint32 nFlags, int iQSlot) {
// Assume failure
bool bSuccess;
if (pszSoundFile != nullptr) {
nFlags |= SOUND_AUTODELETE;
if (nFlags & SND_MEMORY) {
// Hardcoded for wave files
nFlags |= SOUND_WAVE;
} else if (!fileExists(pszSoundFile)) {
logWarning(buildString("Sound File '%s' not found", pszSoundFile));
return false;
}
// WORKAROUND: Hodj may not specify sound type
if (!(nFlags & (SOUND_WAVE | SOUND_MIDI))) {
Common::String name(pszSoundFile);
if (name.hasSuffixIgnoreCase(".wav"))
nFlags |= SOUND_WAVE;
else if (name.hasSuffixIgnoreCase(".mid"))
nFlags |= SOUND_MIDI;
}
// Take care of any last minute cleanup before we start this new sound
CBofSound::audioTask();
CBofSound::stopWaveSounds();
CBofSound *pSound = new CBofSound(/*pWnd*/nullptr, pszSoundFile, (uint16)nFlags);
if ((nFlags & SOUND_QUEUE) == SOUND_QUEUE) {
pSound->setQSlot(iQSlot);
}
bSuccess = pSound->play();
} else {
bSuccess = true;
CBofSound::stopWaveSounds();
}
return bSuccess;
}
bool BofPlaySoundEx(const char *pszSoundFile, uint32 nFlags, int iQSlot, bool bWait) {
// Assume failure
bool bSuccess = false;
if (pszSoundFile != nullptr) {
if ((nFlags & SOUND_MIX) == 0) {
bWait = false;
}
if (!bWait) {
nFlags |= SOUND_AUTODELETE;
}
if (!fileExists(pszSoundFile)) {
logWarning(buildString("Sound File '%s' not found", pszSoundFile));
return false;
}
//CBofWindow *pWnd = CBofApp::getApp()->getMainWindow();
// Take care of any last minute cleanup before we start this new sound
CBofSound::audioTask();
CBofSound *pSound = new CBofSound(/*pWnd*/nullptr, pszSoundFile, (uint16)nFlags);
if ((nFlags & SOUND_QUEUE) == SOUND_QUEUE) {
pSound->setQSlot(iQSlot);
}
bSuccess = pSound->play();
if (bWait) {
while (pSound->isPlaying()) {
CBofSound::audioTask();
}
delete pSound;
}
}
return bSuccess;
}
bool CBofSound::loadSound() {
assert(isValidObject(this));
assert(_szFileName[0] != '\0');
bool bSuccess = true;
if (_pFileBuf == nullptr) {
bSuccess = false;
Common::File in;
if (in.open(_szFileName)) {
_iFileSize = in.size();
_pFileBuf = (byte *)malloc(_iFileSize);
if (in.read(_pFileBuf, _iFileSize) == _iFileSize)
bSuccess = true;
}
}
return bSuccess;
}
bool CBofSound::releaseSound() {
assert(isValidObject(this));
if (!(_wFlags & SND_MEMORY))
free(_pFileBuf);
_pFileBuf = nullptr;
return true;
}
bool CBofSound::soundsPlayingNotOver() {
// Assume no wave sounds are playing
bool bPlaying = false;
// Walk through sound list, and check for sounds that need attention
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (pSound->playing() &&
(pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX) &&
!(pSound->_wFlags & SOUND_OVEROK)) {
bPlaying = true;
break;
}
pSound = (CBofSound *)pSound->getNext();
}
return bPlaying;
}
bool CBofSound::waveSoundPlaying() {
// Assume no wave sounds are playing
bool bPlaying = false;
// Walk through sound list, and check for sounds that need attention
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (pSound->playing() && (pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX)) {
bPlaying = true;
break;
}
pSound = (CBofSound *)pSound->getNext();
}
return bPlaying;
}
bool CBofSound::midiSoundPlaying() {
// Assume no wave sounds are playing
bool bPlaying = false;
// Walk through sound list, and check for sounds that need attention
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (pSound->playing() && (pSound->_wFlags & SOUND_MIDI)) {
bPlaying = true;
break;
}
pSound = (CBofSound *)pSound->getNext();
}
return bPlaying;
}
void CBofSound::audioTask() {
static bool bAlready = false;
// Don't allow recursion here
assert(!bAlready);
bAlready = true;
// Walk through sound list, and check for sounds that need attention
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (!pSound->paused()) {
if ((pSound->_wFlags & SOUND_WAVE) || (pSound->_wFlags & SOUND_MIX)) {
// Has this sound been played?
if (pSound->_bStarted) {
// And, Is it done?
if (!g_system->getMixer()->isSoundHandleActive(pSound->_handle)) {
// Kill it
pSound->stop();
}
} else if (pSound->_bInQueue) {
// If this is a Queued sound, and has not already started
// And it is time to play
if ((CBofSound *)_cQueue[pSound->_iQSlot]->getQItem() == pSound) {
pSound->playWAV();
}
}
} else if ((pSound->_wFlags & SOUND_MIDI) && pSound->_bPlaying) {
// And, Is it done?
if (!g_engine->_midi->isPlaying()) {
// Kill it
pSound->stop();
}
}
}
pSound = (CBofSound *)pSound->getNext();
}
bAlready = false;
}
ErrorCode CBofSound::playWAV() {
assert(isValidObject(this));
if (!errorOccurred()) {
// If it's not yet loaded, then load it now
if (_pFileBuf == nullptr) {
loadSound();
}
assert(_pFileBuf != nullptr);
if (_pFileBuf != nullptr) {
if (_bInQueue) {
setVolume(_nSlotVol[_iQSlot]);
}
// Then, Play it
Common::SeekableReadStream *stream = new Common::MemoryReadStream(_pFileBuf, _iFileSize);
Audio::AudioStream *audio = Audio::makeLoopingAudioStream(Audio::makeWAVStream(stream, DisposeAfterUse::YES), _wLoops);
if (audio == nullptr) {
reportError(ERR_UNKNOWN, "Could not allocate audio stream.");
}
g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_handle, audio, -1, VOLUME_SVM(_nVol));
_bPlaying = true;
_bStarted = true;
}
}
return _errCode;
}
ErrorCode CBofSound::flushQueue(int nSlot) {
assert(nSlot >= 0 && nSlot < NUM_QUEUES);
// Assume no error
ErrorCode errorCode = ERR_NONE;
// Remove all queued sounds
_cQueue[nSlot]->flush();
// Including any that are currently playing
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
// Prefetch next sound in case stop() deletes this one
CBofSound *pNextSound = pSound->getNext();
// If this sound is playing from specified queue
if (pSound->isPlaying() && pSound->_bInQueue && pSound->_iQSlot == nSlot) {
// Then chuck it
pSound->stop();
}
// Next
pSound = pNextSound;
}
return errorCode;
}
void CBofSound::setQVol(int nSlot, int nVol) {
// Validate input
assert(nSlot >= 0 && nSlot < NUM_QUEUES);
assert(nVol >= 0 && nVol <= VOLUME_INDEX_MAX);
_nSlotVol[nSlot] = nVol;
// Set all Queued sounds in specified slot to this volume
CBofSound *pSound = _pSoundChain;
while (pSound != nullptr) {
if (pSound->_bInQueue && pSound->_iQSlot == nSlot) {
pSound->setVolume(nVol);
}
pSound = pSound->getNext();
}
}
bool MessageBeep(int uType) {
warning("TODO: beep");
return true;
}
} // namespace Bagel

View File

@@ -0,0 +1,247 @@
/* 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_SOUND_H
#define BAGEL_BOFLIB_SOUND_H
#include "audio/mixer.h"
#include "bagel/boflib/stdinc.h"
#include "bagel/boflib/llist.h"
#include "bagel/boflib/object.h"
#include "bagel/boflib/error.h"
#include "bagel/boflib/queue.h"
namespace Bagel {
//
// Wavemix-related constants
//
#define VOLUME_INDEX_MIN 0
#define VOLUME_INDEX_MAX 12
#define VOLUME_INDEX_DEFAULT 10
// Convert to ScummVM scale
#define VOLUME_SVM(x) ((x) * Audio::Mixer::kMaxChannelVolume / VOLUME_INDEX_MAX)
#define SVM_VOLUME(x) (((x) >= 252) ? VOLUME_INDEX_MAX : (x) * VOLUME_INDEX_MAX / 252)
#define SOUND_BUFFERED 0x0001
#define SOUND_ASYNCH 0x0002
#define SOUND_NOTIFY 0x0004
#define SOUND_AUTODELETE 0x0008
#define SOUND_LOOP 0x0010
#define SOUND_WAVE 0x0020
#define SOUND_MIDI 0x0040
#define SOUND_DONT_LOOP_TO_END 0x0080
#define SOUND_QUEUE 0x0100 // With wavemix: play after previous sound finishes
#define SOUND_MIX 0x0200 // Use wavemix to really play asynchronously
#define SOUND_ASAP 0x0400 // Play as soon as a channel is free (maybe now)
#define SOUND_WAIT 0x0800 // For wavemix: Set sound up but don't play it yet
#define SOUND_LOCK 0x1000 // Reserve this channel until user stops it
#define SOUND_PRELOAD 0x2000 // Only works for Resource MAC snd files
#define SOUND_OVEROK 0x4000 // OK to play another sound over this file
#define SND_MEMORY 0x8000 // Raw in-memory sound passed rather than a filename
#define SND_NODEFAULT 0
#define SND_SYNC 0
#define SND_ASYNC SOUND_ASYNCH
#define SOUND_TYPE_WAV 1
#define SOUND_TYPE_XM 2
#define SOUND_TYPE_QT 3
#define SOUND_TYPE_SMF 4
#define FMT_MILLISEC 1 // Time format specifiers.
#define FMT_BPM 2
#define NUM_QUEUES 8
class CBofSound : public CBofError, public CBofObject, public CLList {
public:
friend class MusicPlayer;
CBofSound();
CBofSound(void *pWnd, const char *pszPathName, uint16 wFlags, int nLoops = 1);
virtual ~CBofSound();
void addToSoundChain();
void initialize(const char *pszPathName, uint16 wFlags) {
initialize(nullptr, pszPathName, wFlags);
}
void initialize(void *pWnd, const char *pszPathName, uint16 wFlags);
void setDrivePath(const char *path) {}
bool midiLoopPlaySegment(uint32 LoopBegin, uint32 LoopEnd = 0L, uint32 FirstPassBegin = 0L, uint32 TimeFmt = FMT_MILLISEC);
bool play(uint32 StartOfPlay = 0L, uint32 TimeFmtFlag = FMT_MILLISEC);
bool pause();
bool resume();
void stop();
CBofSound *getNext() {
return (CBofSound *)_pNext;
}
CBofSound *getPrev() {
return (CBofSound *)_pPrev;
}
char *getFileName() {
return &_szFileName[0];
}
void setFlags(uint16 wFlags) {
_wFlags = wFlags;
}
uint16 getFlags() {
return _wFlags;
}
bool playing() {
return isPlaying();
}
bool isPlaying() {
return _bPlaying;
}
bool isQueued() {
return _bInQueue;
}
bool paused() {
return _bPaused;
}
void setQSlot(int nSlot) {
_iQSlot = nSlot;
}
int getQSlot() {
return _iQSlot;
}
void setVolume(int nVol);
int getVolume() {
return _nVol;
}
static void initialize();
static void shutdown();
static void setVolume(int MidiVolume, int WaveVolume);
static bool soundPlaying() {
return (_nCount > 0) ? true : false;
}
static bool waveSoundPlaying();
static bool midiSoundPlaying();
static bool soundsPlayingNotOver();
static void setQVol(int nSlot, int nVol);
ErrorCode playWAV();
static ErrorCode flushQueue(int nSlot);
static void resetQVolumes();
static bool pauseSounds();
static bool resumeSounds();
static void stopSounds();
static void stopWaveSounds();
static void stopMidiSounds();
static void clearSounds();
static void clearWaveSounds();
static void clearMidiSounds();
static void waitSounds();
static void waitWaveSounds();
static void waitMidiSounds();
static bool handleMessages();
static bool bofSleep(uint32 dwTime);
static void audioTask();
static bool soundsPlaying();
static bool MidiAvailable() {
return true;
}
static bool SoundAvailable() {
return true;
}
static bool SoundVolumeAvailable() {
return true;
}
static bool MidiVolumeAvailable() {
return true;
}
static CBofSound *OnMCIStopped(WPARAM wParam, LPARAM lParam) {
return nullptr;
}
static CBofSound *OnMMIOStopped(WPARAM wParam, LPARAM lParam) {
return nullptr;
}
private:
bool loadSound();
bool releaseSound();
private:
char _szFileName[MAX_FNAME]; // Path spec for sound file
int8 _chType = 0; // Type of sound commands used
uint16 _wLoops = 0; // Number of times to loop the sound (0xFFFF means infinite)
uint16 _wFlags = 0; // Flags for playing
bool _bPaused = false; // Whether its paused
bool _bPlaying = false; // Whether its playing
bool _bExtensionsUsed = false;
uint32 _dwPlayStart = 0;
uint32 _dwRePlayStart = 0;
uint32 _dwRePlayEnd = 0;
Audio::SoundHandle _handle;
byte *_pFileBuf = nullptr;
uint32 _iFileSize = 0;
int _iQSlot = 0;
bool _bInQueue = false;
bool _bStarted = false;
int _nVol = 0;
void *_pWnd = nullptr; // Parent window for messages
static char _szDrivePath[MAX_DIRPATH]; // Path spec to drive
static CBofSound *_pSoundChain; // First item in chain or nullptr
static int _nCount; // Count of active sounds
static int _nWavCount; // Number of wave sound devices
static int _nMidiCount; // Number of midi sound devices
static void *_pMainWnd; // Window for message processing
static bool _bInit;
static int _nSlotVol[NUM_QUEUES];
static CQueue *_cQueue[NUM_QUEUES];
};
#define CSound CBofSound
extern bool BofPlaySound(const char *pszSoundFile, uint32 nFlags, int iQSlot = 0);
extern bool BofPlaySoundEx(const char *pszSoundFile, uint32 nFlags, int iQSlot = 0, bool bWait = false);
extern bool MessageBeep(int uType);
#define sndPlaySound BofPlaySound
} // namespace Bagel
#endif

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_BOFLIB_STDINC_H
#define BAGEL_BOFLIB_STDINC_H
#include "common/scummsys.h"
#include "common/rect.h"
#include "bagel/afxwin.h"
namespace Bagel {
/*
* Normal types
*/
typedef void *(*BofCallback)(int, void *);
typedef long Fixed;
/*
* Extended types
*/
struct StSize {
int cx;
int cy;
};
struct StPoint {
int x;
int y;
};
struct Vector {
double x;
double y;
double z;
};
struct WindowPos {
void *hwnd = nullptr;
void *hwndinsertAfter = nullptr;
int x = 0;
int y = 0;
int cx = 0;
int cy = 0;
uint32 flags = 0;
};
#define MAKE_WORD(a, b) ((uint16)(((byte)(a)) | ((uint16)((byte)(b))) << 8))
#define MAKE_LONG(low, high) ((int32)(((uint16)(low)) | (((uint32)((uint16)(high))) << 16)))
/* For big-endian platforms (i.e. MAC) */
#define SWAPWORD(x) MAKE_WORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKE_LONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
#ifndef MAX_FNAME
#define MAX_FNAME 256
#endif
#define MAX_DIRPATH 256
#ifndef PDFT
#define PDFT(VALUE) = VALUE
#endif
/*
* normal types
*/
#define VIRTUAL virtual
#define STATIC static
#define CDECL
#define INLINE inline
} // namespace Bagel
#endif

View File

@@ -0,0 +1,599 @@
/* 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/str.h"
#include "bagel/boflib/string.h"
#include "bagel/boflib/misc.h"
#include "bagel/boflib/string_functions.h"
namespace Bagel {
#define MAX_STRING 256
#define BUF_EXTRA 20
CBofString::CBofString() {
init();
}
CBofString::CBofString(int nLength) {
init();
allocBuffer(nLength);
}
CBofString::CBofString(const CBofString &cString) {
init();
copy(cString._pszData);
}
CBofString::CBofString(const char *pszBuf) {
init();
copy(pszBuf);
}
CBofString::CBofString(char *pszBuff, int pszBuffLen) {
init();
// Force a max length (To stop uninitialized buffer from killing us)
*(pszBuff + pszBuffLen - 1) = '\0';
// Passing in un-initialized data could cause problems depending on what
// string functions are used after this constructor.
_nLength = (uint16)strlen(pszBuff);
// Use the high byte of the buffer size to determine if we're using stack memory.
// Make sure that we don't have an obscenely large string
assert((pszBuffLen & mUseStackMem) == false);
SETBUFFERSIZE(pszBuffLen, true);
_pszData = pszBuff;
}
CBofString::CBofString(char ch, int nRepeat) {
assert(nRepeat > 0);
init();
allocBuffer(nRepeat);
memset(_pszData, ch, nRepeat);
}
CBofString::~CBofString() {
assert(isValidObject(this));
free();
}
void CBofString::init() {
assert(isValidObject(this));
SETBUFFERSIZE(0, false);
_nLength = 0;
_pszData = nullptr;
}
void CBofString::allocBuffer(int nLen) {
assert(isValidObject(this));
assert(nLen >= 0);
// These 3 lines "should" do the same thing
assert(nLen < SHRT_MAX); // max size (enough room for 1 extra)
assert((uint16)nLen < mUseStackMem);
assert((nLen & mUseStackMem) == 0);
// Delete any previous buffer
free();
// Don't do anything about zero length allocations
if (nLen > 0) {
// Allocate a buffer filled with 0s
_pszData = (char *)bofCleanAlloc(nLen + 1);
}
_nLength = 0;
// Use the high byte of the bufflen to indicate if we're using
// stack mem or not. Make sure our buff size is not too big
assert((nLen & mUseStackMem) == 0);
SETBUFFERSIZE(nLen, false);
}
void CBofString::free() {
assert(isValidObject(this));
bool bStackMem = USESSTACKMEM();
// Free any attached data
// Only free if it's not stack memory
if (_pszData != nullptr && bStackMem == false) {
bofFree(_pszData);
_pszData = nullptr;
}
_nLength = 0;
SETBUFFERSIZE(0, bStackMem);
}
void CBofString::copy(const char *pszBuf) {
assert(isValidObject(this));
if (NORMALIZEBUFFERSIZE() != 0)
*_pszData = '\0';
_nLength = 0;
if (pszBuf != nullptr) {
int n = strlen(pszBuf);
if (NORMALIZEBUFFERSIZE() <= n) {
allocBuffer(n + 1);
}
Common::strcpy_s(_pszData, n + 1, pszBuf);
_nLength = (uint16)strlen(_pszData);
}
}
void CBofString::allocCopy(CBofString &dest, int nCopyLen, int nCopyIndex, int nExtraLen) const {
assert(isValidObject(this));
// Will clone the data attached to this string allocating 'nExtraLen' characters
// Places results in uninitialized string 'dest'
// Will copy the part or all of original data to start of new string
int nNewLen = nCopyLen + nExtraLen;
if (nNewLen == 0) {
dest.free();
} else {
dest.allocBuffer(nNewLen);
assert(_pszData != nullptr);
memcpy(dest._pszData, &_pszData[nCopyIndex], nCopyLen * sizeof(char));
}
}
const CBofString &CBofString::operator=(const CBofString &cString) {
assert(isValidObject(this));
copy(cString._pszData);
return *this;
}
const CBofString &CBofString::operator=(const char *lpsz) {
assert(isValidObject(this));
copy(lpsz);
return *this;
}
void CBofString::concatCopy(int nSrc1Len, const char *lpszSrc1Data, int nSrc2Len, const char *lpszSrc2Data, int nAllocLen) {
assert(isValidObject(this));
// -- Master concatenation routine
// concatenate two sources
// -- Assume that 'this' is a new CBofString object
int nNewLen = nSrc1Len + nSrc2Len;
allocBuffer((nAllocLen == 0 ? nNewLen : nAllocLen));
memcpy(_pszData, lpszSrc1Data, nSrc1Len * sizeof(char));
memcpy(&_pszData[nSrc1Len], lpszSrc2Data, nSrc2Len * sizeof(char));
// RMS
_nLength = (uint16)nNewLen;
}
CBofString operator+(const CBofString &string1, const CBofString &string2) {
CBofString s;
s.concatCopy(string1._nLength, string1._pszData, string2._nLength, string2._pszData);
return s;
}
CBofString operator+(const CBofString &string, const char *lpsz) {
CBofString s;
s.concatCopy(string._nLength, string._pszData, CBofString::safeStrlen(lpsz), lpsz);
return s;
}
CBofString operator+(const char *lpsz, const CBofString &string) {
CBofString s;
s.concatCopy(CBofString::safeStrlen(lpsz), lpsz, string._nLength, string._pszData);
return s;
}
void CBofString::concatInPlace(int nSrcLen, const char *lpszSrcData) {
char szLocalBuff[512];
assert(isValidObject(this));
// -- The main routine for += operators
// If the buffer is too small, or we have a width mis-match, just
// allocate a new buffer (slow but sure)
//
// Make sure we have an underlying buffer.
if (_nLength + nSrcLen >= NORMALIZEBUFFERSIZE()) {
// Don't increment by buf extra, but set the size if we're
// less than that default threshold.
int nAllocAmount = nSrcLen;
if (nAllocAmount < BUF_EXTRA) {
nAllocAmount = BUF_EXTRA;
}
if (NORMALIZEBUFFERSIZE() == 0) {
allocBuffer(_nLength + nAllocAmount);
memcpy(_pszData, lpszSrcData, nSrcLen);
*(_pszData + nSrcLen) = '\0';
_nLength = (uint16)(_nLength + (uint16)nSrcLen);
} else {
assert(_pszData != nullptr);
// We have to grow the buffer, use the concat in place routine
char *lpszOldData;
if ((_nLength + nSrcLen + 1) < 512)
lpszOldData = szLocalBuff;
else
lpszOldData = new char[_nLength + nSrcLen + 1];
memcpy(lpszOldData, _pszData, (_nLength + 1) * sizeof(char));
concatCopy(_nLength, lpszOldData, nSrcLen, lpszSrcData, _nLength + nAllocAmount);
if (lpszOldData != szLocalBuff)
delete[] lpszOldData;
}
} else {
// Fast concatenation when buffer big enough
// Optimize for a single byte
if (nSrcLen == 1) {
_pszData[_nLength] = *lpszSrcData;
} else {
memcpy(&_pszData[_nLength], lpszSrcData, nSrcLen * sizeof(char));
}
_nLength = (uint16)(_nLength + (uint16)nSrcLen);
}
assert(_nLength <= NORMALIZEBUFFERSIZE());
_pszData[_nLength] = '\0';
}
const CBofString &CBofString::operator+=(const char *lpsz) {
assert(isValidObject(this));
concatInPlace(safeStrlen(lpsz), lpsz);
return *this;
}
const CBofString &CBofString::operator+=(char ch) {
assert(isValidObject(this));
concatInPlace(1, &ch);
return *this;
}
const CBofString &CBofString::operator+=(const CBofString &string) {
assert(isValidObject(this));
concatInPlace(string._nLength, string._pszData);
return *this;
}
char *CBofString::getBuffer() {
assert(isValidObject(this));
if (_pszData == nullptr) {
allocBuffer(1);
}
return _pszData;
}
int CBofString::findNumOccurrences(const char *pszSub) {
assert(isValidObject(this));
assert(pszSub != nullptr);
assert(*pszSub != '\0');
int nHits = 0;
if (_pszData != nullptr) {
char *pszCur = _pszData;
while (pszCur != nullptr) {
pszCur = strstr(pszCur, pszSub);
if (pszCur != nullptr) {
nHits++;
pszCur++;
}
}
}
return nHits;
}
const CBofString &CBofString::operator=(char ch) {
assert(isValidObject(this));
char szBuf[4];
Common::sprintf_s(szBuf, "%c", ch);
copy(szBuf);
return *this;
}
CBofString operator+(const CBofString &string1, char ch) {
CBofString s;
s.concatCopy(string1._nLength, string1._pszData, 1, &ch);
return s;
}
CBofString operator+(char ch, const CBofString &string) {
CBofString s;
s.concatCopy(1, &ch, string._nLength, string._pszData);
return s;
}
CBofString CBofString::mid(int nFirst) const {
assert(isValidObject(this));
return mid(nFirst, _nLength - nFirst);
}
CBofString CBofString::mid(int nFirst, int nCount) const {
assert(isValidObject(this));
assert(nFirst >= 0);
assert(nCount >= 0);
// Out-of-bounds requests return sensible things
if (nFirst + nCount > _nLength)
nCount = _nLength - nFirst;
if (nFirst > _nLength)
nCount = 0;
CBofString dest;
allocCopy(dest, nCount, nFirst, 0);
return dest;
}
CBofString CBofString::right(int nCount) const {
assert(isValidObject(this));
assert(nCount >= 0);
if (nCount > _nLength)
nCount = _nLength;
CBofString dest;
allocCopy(dest, nCount, _nLength - nCount, 0);
return dest;
}
CBofString CBofString::left(int nCount) const {
assert(isValidObject(this));
assert(nCount >= 0);
if (nCount > _nLength)
nCount = _nLength;
CBofString dest;
allocCopy(dest, nCount, 0, 0);
return dest;
}
void CBofString::deleteLastChar() {
if (!isEmpty()) {
*(_pszData + _nLength - 1) = '\0';
--_nLength;
}
}
// Find a sub-string (like strstr)
int CBofString::find(const char *lpszSub) const {
assert(isValidObject(this));
// Find first matching substring
char *lpsz = nullptr;
if (_pszData != nullptr)
lpsz = strstr(_pszData, lpszSub);
// Return -1 for not found, distance from beginning otherwise
return (lpsz == nullptr) ? -1 : (int)(lpsz - _pszData);
}
// CBofString formatting
#define FORCE_ANSI 0x10000
#define FORCE_UNICODE 0x20000
int CBofString::safeStrlen(const char *psz) {
return (psz == nullptr) ? 0 : strlen(psz);
}
// CBofString support (windows specific)
//
int CBofString::compare(const char *psz) const {
assert(isValidObject(this));
assert(psz != nullptr);
int n = -1;
if (_pszData != nullptr)
n = strcmp(_pszData, psz);
return n;
}
int CBofString::compareNoCase(const char *psz) const {
assert(isValidObject(this));
int n = -1;
if (_pszData != nullptr)
n = scumm_stricmp(_pszData, psz);
return n;
}
char CBofString::getAt(int nIndex) {
assert(isValidObject(this));
assert(nIndex >= 0);
assert(nIndex < _nLength);
return _pszData[nIndex];
}
char CBofString::operator[](int nIndex) {
assert(isValidObject(this));
return getAt(nIndex);
}
void CBofString::replaceCharAt(int nIndex, char chNew) {
if (_pszData != nullptr && nIndex < _nLength) {
_pszData[nIndex] = chNew;
}
}
void CBofString::replaceChar(char chOld, char chNew) {
assert(isValidObject(this));
// Would never find the terminator
assert(chOld != '\0');
if (_pszData != nullptr) {
// Walk through the string and replace the specified character
char *p = _pszData;
for (int i = 0; i < _nLength; i++) {
if (*p == chOld) {
*p = chNew;
// If we just inserted the terminator, then the length of
// this string has been changed, and we don't have to search
// any more.
//
if (chNew == '\0') {
_nLength = (uint16)i;
break;
}
}
p++;
}
}
}
void CBofString::replaceStr(const char *pszOld, const char *pszNew) {
assert(isValidObject(this));
assert(pszOld != nullptr);
assert(pszNew != nullptr);
if (_pszData != nullptr) {
char *p, *pszSearch;
int nOldLen = strlen(pszOld);
int nNewLen = strlen(pszNew);
// 1st pass to determine how much more storage space we might need
if (nNewLen > nOldLen) {
int nDiff = nNewLen - nOldLen;
int nNeedLength = _nLength + 1;
p = _pszData;
pszSearch = strstr(p, pszOld);
while (pszSearch != nullptr) {
p = pszSearch + nOldLen;
nNeedLength += nDiff;
pszSearch = strstr(p, pszOld);
}
// If we need more storage space for the buffer, then get some
if (nNeedLength > NORMALIZEBUFFERSIZE()) {
growTo(nNeedLength);
}
}
// Loop on the search and replace
// Make sure we loop on this, not just once as we can have several occurrences
// of the token that we are searching for.
p = _pszData;
pszSearch = strstr(p, pszOld);
while (pszSearch != nullptr) {
strreplaceStr(p, pszOld, pszNew);
p = pszSearch + nNewLen;
pszSearch = strstr(p, pszOld);
}
// Get new length
_nLength = (uint16)strlen(_pszData);
}
}
void CBofString::growTo(int nNewSize) {
assert(isValidObject(this));
// If there is nothing in the buffer to save, then just allocate what
// is needed
if (_nLength == 0) {
allocBuffer(nNewSize);
} else {
// Otherwise, we must keep track of whats in the buffer
// Create a temp buffer to save string
char *p = (char *)bofAlloc(_nLength + 2);
// Save copy of string
Common::strcpy_s(p, MAX_STRING, _pszData);
// Make the new buffer
allocBuffer(nNewSize);
// Copy saved string back
strncpy(_pszData, p, nNewSize - 1);
// Get it's new length
_nLength = (uint16)strlen(_pszData);
// Don't need temp buffer anymore
bofFree(p);
}
}
int CBofString::hash() const {
int returnValue = 0;
// Needs to be case in-sensitive
for (int i = 0; i < _nLength; i++) {
returnValue = returnValue + (char)toupper(_pszData[i]);
}
return returnValue;
}
void CBofString::makeUpper() {
Common::String s(_pszData);
s.toUppercase();
strncpy(_pszData, s.c_str(), _nLength);
}
} // namespace Bagel

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/>.
*
*/
#ifndef BAGEL_BOFLIB_STRING_H
#define BAGEL_BOFLIB_STRING_H
#include "common/system.h"
#include "bagel/boflib/object.h"
namespace Bagel {
// The buffer size and string len members are shorts, and use the high byte
// of the buffer size to tell us if it is stack memory being used.
#define mUseStackMem 0x8000
#define NORMALIZEBUFFERSIZE() (_nBufferSize & ~mUseStackMem)
#define SETBUFFERSIZE(size, usestackmem) (_nBufferSize = (uint16)((size) + ((usestackmem) ? mUseStackMem : 0)))
#define USESSTACKMEM() (_nBufferSize & mUseStackMem)
class CBofString : public CBofObject {
public:
// Constructors
/**
* Default constructor
*/
CBofString();
/**
* Construct a string from a null terminated string
* @param pszBuf Source string
*/
CBofString(const char *pszBuf);
/**
* Construct a string based on a source string
*/
CBofString(const CBofString &stringSrc);
/**
* Construct a string with a single character repeated a number of times
* @param ch Character to use
* @param nRepeat Number of repeats
*/
CBofString(char ch, int nRepeat = 1);
/**
* Constructs a string, and sets initial buffer size
* @param nLength String length
*/
CBofString(int nLength);
/**
* Construct a string based on a subset of a passed null terminated string
* @brief This modifies the passed source string to null terminate the substring
* @param pszBuff Source string
* @param pszBuffLen Substring length
*/
CBofString(char *pszBuff, int pszBuffLen);
/**
* Destructor
*/
virtual ~CBofString();
// Attributes & Operations
int getBufferSize() const {
return NORMALIZEBUFFERSIZE();
}
int getLength() const {
return _nLength;
}
bool isEmpty() const {
return _nLength == 0;
}
/**
* De-Allocates internal buffer for current CBofString
*/
void free();
void growTo(int nNewSize); // Resize the buffer
char getAt(int nIndex); // 0 based
char operator[](int nIndex); // same as getAt
operator const char *() const {
return (const char *)_pszData;
}
const char *getBuffer() const {
return _pszData;
}
// Hashing support.
//
int hash() const;
// Overloaded assignment
/**
* Copies specified string into current CBofString
* @param pszSourceBuf Buffer to copy
*/
void copy(const char *pszSourceBuf);
const CBofString &operator=(const CBofString &cStringSrc);
const CBofString &operator=(char ch);
const CBofString &operator=(const char *psz);
// String concatenation
const CBofString &operator+=(const CBofString &cString);
const CBofString &operator+=(char ch);
const CBofString &operator+=(const char *psz);
friend CBofString operator+(const CBofString &string1, const CBofString &string2);
friend CBofString operator+(const CBofString &string, char ch);
friend CBofString operator+(char ch, const CBofString &string);
friend CBofString operator+(const CBofString &string, const char *lpsz);
friend CBofString operator+(const char *lpsz, const CBofString &string);
// String comparison
int compare(const char *lpsz) const; // straight character
int compareNoCase(const char *lpsz) const; // ignore case
// Simple sub-string extraction
//
CBofString mid(int nFirst, int nCount) const;
CBofString mid(int nFirst) const;
CBofString left(int nCount) const;
CBofString right(int nCount) const;
void deleteLastChar();
// Upper/lower/reverse conversion
void makeUpper();
// Searching (return starting index, or -1 if not found)
// Look for a specific sub-string
int find(const char *lpszSub) const; // like "C" strstr
int findNumOccurrences(const char *pszSub);
// Search and replace routines
void replaceCharAt(int, char);
void replaceChar(char chOld, char chNew);
void replaceStr(const char *pszOld, const char *pszNew);
// Access to string implementation buffer as "C" character array
char *getBuffer();
protected:
// implementation helpers
/**
* initialize current CBofString members
*/
void init();
/**
* Allocates specified string into specified destination
*/
void allocCopy(CBofString &dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
/**
* Allocates internal buffer for current CBofString
* @param nLen Initial buffer size
*/
void allocBuffer(int nLen);
void concatCopy(int nSrc1Len, const char *lpszSrc1Data, int nSrc2Len, const char *lpszSrc2Data, int nAllocLen = 0);
void concatInPlace(int nSrcLen, const char *lpszSrcData);
static int safeStrlen(const char *lpsz);
// Lengths/sizes in characters
// (note: an extra character is always allocated)
//
char *_pszData; // actual string (zero terminated)
uint16 _nLength; // does not include terminating 0
uint16 _nBufferSize; // does not include terminating 0
};
// Inline Comparison operators
//
inline bool operator==(const CBofString &s1, const CBofString &s2) {
return s1.compare(s2) == 0;
}
inline bool operator==(const CBofString &s1, const char *s2) {
return s1.compare(s2) == 0;
}
inline bool operator==(const char *s1, const CBofString &s2) {
return s2.compare(s1) == 0;
}
inline bool operator!=(const CBofString &s1, const CBofString &s2) {
return s1.compare(s2) != 0;
}
inline bool operator!=(const CBofString &s1, const char *s2) {
return s1.compare(s2) != 0;
}
inline bool operator!=(const char *s1, const CBofString &s2) {
return s2.compare(s1) != 0;
}
inline bool operator<(const CBofString &s1, const CBofString &s2) {
return s1.compare(s2) < 0;
}
inline bool operator<(const CBofString &s1, const char *s2) {
return s1.compare(s2) < 0;
}
inline bool operator<(const char *s1, const CBofString &s2) {
return s2.compare(s1) > 0;
}
inline bool operator>(const CBofString &s1, const CBofString &s2) {
return s1.compare(s2) > 0;
}
inline bool operator>(const CBofString &s1, const char *s2) {
return s1.compare(s2) > 0;
}
inline bool operator>(const char *s1, const CBofString &s2) {
return s2.compare(s1) < 0;
}
inline bool operator<=(const CBofString &s1, const CBofString &s2) {
return s1.compare(s2) <= 0;
}
inline bool operator<=(const CBofString &s1, const char *s2) {
return s1.compare(s2) <= 0;
}
inline bool operator<=(const char *s1, const CBofString &s2) {
return s2.compare(s1) >= 0;
}
inline bool operator>=(const CBofString &s1, const CBofString &s2) {
return s1.compare(s2) >= 0;
}
inline bool operator>=(const CBofString &s1, const char *s2) {
return s1.compare(s2) >= 0;
}
inline bool operator>=(const char *s1, const CBofString &s2) {
return s2.compare(s1) <= 0;
}
} // namespace Bagel
#endif

View File

@@ -0,0 +1,98 @@
/* 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/str.h"
#include "bagel/boflib/string_functions.h"
namespace Bagel {
int strCharCount(const char *str, char c) {
assert(str != nullptr);
int n = 0;
while (*str != '\0') {
if (*str++ == c)
n++;
}
return n;
}
char *strreplaceChar(char *str, char cOld, char cNew) {
char *p = str;
// Can't access a nullptr pointer
assert(str != nullptr);
// If cOld was '\0' then this function would do nothing
assert(cOld != '\0');
while (*p != '\0') {
if (*p == cOld) {
*p = cNew;
}
p++;
}
return str;
}
char *strreplaceStr(char *pszBuf, const char *pszTok, const char *pszNewTok) {
// Can't access nullptr pointers
assert(pszBuf != nullptr);
assert(pszTok != nullptr);
assert(pszNewTok != nullptr);
// Search token, and new token can't be the same
assert(strcmp(pszTok, pszNewTok) != 0);
int nTok = strlen(pszTok);
int nNewTok = strlen(pszNewTok);
int nDiff = nTok - nNewTok;
char *p = pszBuf;
for (char *pszSearch = strstr(p, pszTok); pszSearch; pszSearch = strstr(p, pszTok)) {
char *pszEndTok = pszSearch + nTok;
if (nDiff != 0) {
memmove(pszEndTok - nDiff, pszEndTok, strlen(pszEndTok) + 1);
}
memcpy(pszSearch, pszNewTok, nNewTok);
}
return pszBuf;
}
void memreplaceChar(byte *pBuf, byte chOld, byte chNew, int32 lSize) {
assert(pBuf != nullptr);
assert(chOld != chNew);
while (lSize-- > 0) {
if (*pBuf == chOld) {
*pBuf = chNew;
}
pBuf++;
}
}
} // namespace Bagel

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/>.
*
*/
#ifndef BAGEL_BOFLIB_STRING_FUNCTIONS_H
#define BAGEL_BOFLIB_STRING_FUNCTIONS_H
namespace Bagel {
/**
* Counts number of occurrences of a specified char in String
* @param str Pointer to string to parse
* @param c Character to count in str
* @return Number of times character c occurs in string str
*/
extern int strCharCount(const char *str, char c);
/**
* Replaces all occurrences of cOld in string with cNew
* @param pszbuf String to search
* @param cOld Character to find in pszBuf
* @param cNew Character to replace cOld
* @return Pointer to pszBuf
*/
extern char *strreplaceChar(char *pszbuf, char cOld, char cNew);
/**
* Replaces every occurrence of 1 character with another
* @param pBuf Buffer to search
* @param chOld Old character to be replaced
* @param chNew New character to replace with
* @param lSize Size of buffer
*/
extern void memreplaceChar(byte *pBuf, byte chOld, byte chNew, int32 lSize);
/**
* Replaces all tokens in string with new token
* @param pszBuf Buffer to search
* @param pszTok1 Token to search for in pszBuf
* @param pszTok2 Replacement token
* @return Pointer to pszBuf.
*/
extern char *strreplaceStr(char *pszBuf, const char *pszTok1, const char *pszTok2);
} // namespace Bagel
#endif

View File

@@ -0,0 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
add_engine bagel "BAGEL" yes "" "" "16bit highres freetype2" "midi"

6
engines/bagel/credits.pl Normal file
View File

@@ -0,0 +1,6 @@
begin_section("Bagel");
add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
add_person("Daniel Albano", "SupSuper", "");
add_person("Eugene Sandulenko", "sev", "");
add_person("Paul Gilbert", "dreammaster", "");
end_section();

View File

@@ -0,0 +1,30 @@
/* 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/detection.h"
#include "bagel/detection_tables.h"
BagelMetaEngineDetection::BagelMetaEngineDetection() : AdvancedMetaEngineDetection(Bagel::gameDescriptions, Bagel::bagelGames) {
_guiOptions = GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD);
_flags = kADFlagMatchFullPaths;
}
REGISTER_PLUGIN_STATIC(BAGEL_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, BagelMetaEngineDetection);

56
engines/bagel/detection.h Normal file
View File

@@ -0,0 +1,56 @@
/* 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_DETECTION_H
#define BAGEL_DETECTION_H
#include "engines/advancedDetector.h"
namespace Bagel {
extern const PlainGameDescriptor bagelGames[];
extern const ADGameDescription gameDescriptions[];
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
} // End of namespace Bagel
class BagelMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
public:
BagelMetaEngineDetection();
~BagelMetaEngineDetection() override {}
const char *getName() const override {
return "bagel";
}
const char *getEngineName() const override {
return "BAGEL"; // the Boffo Adventure Game Engine and Libraries
}
const char *getOriginalCopyright() const override {
return "Copyright(C) 1996 Boffo Games, Inc.";
}
};
#endif // BAGEL_DETECTION_H

View File

@@ -0,0 +1,144 @@
/* 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/>.
*
*/
namespace Bagel {
const PlainGameDescriptor bagelGames[] = {
{ "bagel", "Bagel" },
{ "spacebar", "The Space Bar" },
{ "hodjnpodj", "Hodj 'n' Podj" },
{ "mazeodoom", "Hodj 'n' Podj - Maze O' Doom" },
{ "artparts", "Hodj 'n' Podj - Art Parts" },
{ 0, 0 }
};
const ADGameDescription gameDescriptions[] = {
{
"spacebar",
nullptr,
AD_ENTRY2s("wld/bar.wld", "34b52995cb7e6c68bac22c14cb6813da", 812794,
"zzazzl/pda/zzoom.bmp", "b64f8b34f5107d8812e1372993d43adb", 1678),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
{
"spacebar",
"Not Installed",
AD_ENTRY2s("spacebar/wld/bar.wld", "34b52995cb7e6c68bac22c14cb6813da", 812794,
"zzazzl/pda/zzoom.bmp", "b64f8b34f5107d8812e1372993d43adb", 1678),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
{
"spacebar",
"Small Demo",
AD_ENTRY2s("wld/bar.wld", "47b51863dfaba358843c152a78da664e", 13187,
"bar/pda/bzoom.bmp", "c05189dee78365eca067f58d444e8488", 4114),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO,
GUIO1(GUIO_NONE)
},
{
"spacebar",
"Medium Demo",
AD_ENTRY2s("wld/bar.wld", "4d6a0926484e1660035af0ed4004a47f", 27495,
"zzazzl/pda/zzoom.bmp", "b64f8b34f5107d8812e1372993d43adb", 1678),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO,
GUIO1(GUIO_NONE)
},
{
"spacebar",
nullptr,
AD_ENTRY2s("wld/bar.wld", "a1c4ef26823d729c03b10bcee3063051", 836864,
"zzazzl/pda/zzoom.bmp", "b64f8b34f5107d8812e1372993d43adb", 1678),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
{
"spacebar",
"Not Installed",
AD_ENTRY2s("spacebar/wld/bar.wld", "a1c4ef26823d729c03b10bcee3063051", 836864,
"zzazzl/pda/zzoom.bmp", "b64f8b34f5107d8812e1372993d43adb", 1678),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
{
"hodjnpodj",
nullptr,
AD_ENTRY2s("video/hodj.avi", "6c565ce6e4ab878c7f26e1d344e211a7", 3653624,
"meta/meta.gtl", "35f9d5c944f718768a233d9d62447d07", 43441),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO1(GUIO_NONE)
},
{
"mazeodoom",
nullptr,
AD_ENTRY1s("art/modparts.bmp", "2d8fae58e0cb21cedc118b3a1bcf142b", 11998),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO,
GUIO1(GUIO_NONE)
},
{
"artparts",
nullptr,
AD_ENTRY1s("arttemp.bmp", "ec4897660a14cb73f4fe7d714acaab7a", 308278),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO,
GUIO1(GUIO_NONE)
},
{
"hodjnpodj",
"Demo",
AD_ENTRY1s("hnpdemo.exe", "5200631d37e258651ee0037f32262b49", 147040),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO,
GUIO1(GUIO_NONE)
},
AD_TABLE_END_MARKER
};
} // End of namespace Bagel

View File

@@ -0,0 +1,99 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/hodjnpodj/archeroids/init.h"
#include "bagel/hodjnpodj/archeroids/main.h"
namespace Bagel {
namespace HodjNPodj {
namespace Archeroids {
HINSTANCE hDLLInst;
HINSTANCE hExeInst;
// global the pointer to the your game's main window
HWND ghParentWnd;
extern LPGAMESTRUCT pGameParams;
/////////////////////////////////////////////////////////////////////////////
// Public C interface
/*****************************************************************
*
* RunArch
*
* FUNCTIONAL DESCRIPTION:
*
* This is the API function for the DLL. It is what the calling app
* calls to invoke poker
*
* FORMAL PARAMETERS:
*
* hParentWnd, lpGameInfo
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
HWND FAR PASCAL RunArch(HWND hParentWnd, LPGAMESTRUCT lpGameInfo) {
CMainWindow *pMainWnd;
pGameParams = lpGameInfo;
// invoke you game here by creating a pGame for your main window
// look at the InitInstance for your game for this
ghParentWnd = hParentWnd;
if ((pMainWnd = new CMainWindow) != nullptr) {
pMainWnd->ShowWindow(SW_SHOWNORMAL);
pMainWnd->UpdateWindow();
pMainWnd->SetActiveWindow();
if (pGameParams->bPlayingMetagame)
pMainWnd->PlayGame();
}
// these must be set in this function
hDLLInst = (HINSTANCE)GetWindowWord(pMainWnd->m_hWnd, GWW_HINSTANCE);
hExeInst = (HINSTANCE)GetWindowWord(hParentWnd, GWW_HINSTANCE);
return pMainWnd->m_hWnd; // return the m_hWnd of your main game window
}
} // namespace Archeroids
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,37 @@
/* 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 HODJNPODJ_ARCHEROIDS_DLLINIT_H
#define HODJNPODJ_ARCHEROIDS_DLLINIT_H
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
namespace Bagel {
namespace HodjNPodj {
namespace Archeroids {
HWND FAR PASCAL RunArch(HWND, LPGAMESTRUCT);
} // namespace Archeroids
} // namespace HodjNPodj
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
/* 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 HODJNPODJ_ARCHEROIDS_MAIN_H
#define HODJNPODJ_ARCHEROIDS_MAIN_H
#include "bagel/afxwin.h"
#include "bagel/boflib/error.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/boflib/sound.h"
#include "bagel/hodjnpodj/hnplibs/sprite.h"
#include "bagel/boflib/llist.h"
#include "bagel/hodjnpodj/archeroids/usercfg.h"
namespace Bagel {
namespace HodjNPodj {
namespace Archeroids {
class CMainWindow : public CFrameWnd {
public:
CMainWindow();
void PlayGame();
void PlayNextWave();
void PaintScreen();
ERROR_CODE RepaintSpriteList(CDC *);
void LoadIniSettings();
bool MainLoop();
protected:
void FlushInputEvents();
bool CheckMessages();
ERROR_CODE LoadMasterSprites();
void ReleaseMasterSprites();
ERROR_CODE LoadMasterSounds();
void ReleaseMasterSounds();
void InitializeJoystick();
void GameReset();
void WaveReset();
CSprite *NewLife(int);
ERROR_CODE CreateLives();
ERROR_CODE CreateGoodGuy();
ERROR_CODE CreateBadGuys();
ERROR_CODE CreateHay();
ERROR_CODE CreateBurningHay(CPoint);
ERROR_CODE CreateGoodArrow();
ERROR_CODE CreateBadArrow(CSprite *);
void GamePause();
void GameResume();
void DestroyGoodArrow(CLList *);
void DestroyBadArrow(CLList *);
void DestroyBadGuy(CLList *, CDC *);
void PruneDeadBadGuys();
void DestroyHay(CLList *, CRect, CDC *, bool);
void DeleteSprite(CSprite *);
bool MoveArrows(CDC *);
bool MoveBadGuys(CDC *);
void MoveHodj(int);
void LoseLife(CDC *, bool);
void HandleError(ERROR_CODE);
void KillAnimation();
void OnSoundNotify(CSound *pSound);
POINT GetLeftMostBadGuy();
virtual bool OnCommand(WPARAM, LPARAM) override;
void OnPaint();
void OnSysKeyDown(unsigned int, unsigned int, unsigned int);
void OnKeyDown(unsigned int, unsigned int, unsigned int);
void OnSysChar(unsigned int, unsigned int, unsigned int);
void OnTimer(uintptr);
void OnClose();
long OnJoyStick(unsigned int, long);
void OnActivate(unsigned int, CWnd *, bool) override;
void OnLButtonDown(unsigned int, CPoint);
void OnRButtonUp(unsigned int, CPoint);
void OnMouseMove(unsigned int, CPoint);
LRESULT OnMCINotify(WPARAM, LPARAM);
LRESULT OnMMIONotify(WPARAM, LPARAM);
DECLARE_MESSAGE_MAP()
//
// protected data members
//
CRect m_rNewGameButton;
CPalette *m_pGamePalette = nullptr;
CSprite *m_pMasterBadArrow = nullptr;
CSprite *m_pMasterGoodArrow = nullptr;
CSprite *m_pMasterBurn = nullptr;
CSprite *m_pMasterBadWalk = nullptr;
CSprite *m_pMasterBadShoot = nullptr;
CSprite *m_pMasterBadDie = nullptr;
CSprite *m_pMasterGoodWalk = nullptr;
CSprite *m_pMasterGoodShoot = nullptr;
CSprite *m_pMasterGoodDie = nullptr;
CSprite *m_pMasterHeart = nullptr;
CSprite *m_pHodj = nullptr;
CSprite *m_pScrollSprite = nullptr;
CSprite *m_pLives[LIVES_MAX] = {};
CLList *m_pBadGuyList = nullptr;
CLList *m_pBadArrowList = nullptr;
CLList *m_pGoodArrowList = nullptr;
CLList *m_pHayList = nullptr;
CLList *m_pFXList = nullptr;
CSound *m_pSoundTrack = nullptr;
char * m_pBadDieSound = nullptr;
char * m_pBoltSound = nullptr;
char * m_pArrowSound = nullptr;
char * m_pBurnSound = nullptr;
char * m_pExtraLifeSound = nullptr;
HANDLE m_hBadDieRes = nullptr;
HANDLE m_hBoltRes = nullptr;
HANDLE m_hArrowRes = nullptr;
HANDLE m_hBurnRes = nullptr;
HANDLE m_hExtraLifeRes = nullptr;
POINT m_ptAnchor;
unsigned long m_lScore = 0;
unsigned long m_lNewLifeScore = 0;
int m_nGoodArrows, m_nBadArrows = 0;
int m_nGameSpeed = 0;
unsigned int m_nBadGuySpeed = 0;
unsigned int m_nArrowSpeed = 0;
unsigned int m_nState = 0;
int m_nMoveArrows = 0;
int m_nBadGuys = 0;
int m_nLives = 0;
int m_nLevel = 0;
int m_nWave = 0;
unsigned int m_nJoyLast = 0;
bool m_bPause = false;
bool m_bGameActive = false;
bool m_bJoyActive = false;
bool m_bMoveMode = false;
bool m_bInMenu = false;
bool m_bNewGame = false;
bool m_bAnimationsOn = false;
bool m_bTimerActive = false;
// User Setup variables
//
int m_nInitGameSpeed = 0;
int m_nInitArcherLevel = 0;
int m_nInitNumLives = 0;
int m_nInitNumBadGuys = 0;
};
////
//
// CTheApp:
//
class CTheApp : public CWinApp {
public:
bool InitInstance();
virtual int ExitInstance();
};
} // namespace Archeroids
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,439 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/hnplibs/menures.h"
#include "bagel/hodjnpodj/archeroids/usercfg.h"
namespace Bagel {
namespace HodjNPodj {
namespace Archeroids {
#define ID_OK 101
#define ID_CANCEL 102
#define ID_RESET 103
#define ID_GAMESPEED 112
#define ID_LIVES 110
#define ID_ARCHER_LEVEL 107
#define ID_BADGUYS 113
#define IDS_GAMESPEED 104
#define IDS_LIVES 111
#define IDS_ARCHER_LEVEL 108
extern const char *INI_SECTION;
static const char *apszSpeeds[10] = {
"Injured Snail",
"Snail",
"Turtle",
"Old Gray Mare",
"Ferret",
"Rabbit",
"Race Horse",
"Cheetah",
"Scared Cheetah",
"Cheetah on Steroids"
};
static CColorButton *pOKButton = nullptr; // OKAY button on scroll
static CColorButton *pCancelButton = nullptr; // Cancel button on scroll
static CColorButton *pDefaultsButton = nullptr; // Defaults button on scroll
CUserCfgDlg::CUserCfgDlg(CWnd *pParent, CPalette *pPalette, unsigned int nID)
: CBmpDialog(pParent, pPalette, nID, ".\\ART\\SSCROLL.BMP") {
m_nInitGameSpeed = DEFAULT_GAME_SPEED;
m_nInitArcherLevel = DEFAULT_ARCHER_LEVEL;
m_nInitNumLives = DEFAULT_LIVES;
m_nInitNumBadGuys = DEFAULT_BADGUYS;
DoModal();
}
void CUserCfgDlg::PutDlgData() {
char buf[20];
CDC *pDC;
pDC = GetDC();
m_pTxtSpeedSetting->DisplayString(pDC, apszSpeeds[m_nInitGameSpeed - 1], 14, TEXT_BOLD, RGB(0, 0, 0));
Common::sprintf_s(buf, "Level: %d", m_nInitArcherLevel);
m_pTxtLevel->DisplayString(pDC, buf, 14, TEXT_BOLD, RGB(0, 0, 0));
Common::sprintf_s(buf, "Lives: %d", m_nInitNumLives);
m_pTxtLives->DisplayString(pDC, buf, 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
MFC::SetScrollPos(GetDlgItem(IDS_GAMESPEED)->m_hWnd, SB_CTL, m_nInitGameSpeed, true);
MFC::SetScrollPos(GetDlgItem(IDS_LIVES)->m_hWnd, SB_CTL, m_nInitNumLives, true);
MFC::SetScrollPos(GetDlgItem(IDS_ARCHER_LEVEL)->m_hWnd, SB_CTL, m_nInitArcherLevel, true);
}
bool CUserCfgDlg::OnCommand(WPARAM wParam, LPARAM lParam) {
/*
* respond to user
*/
if (HIWORD(lParam) == BN_CLICKED) {
switch (wParam) {
case ID_OK:
m_bShouldSave = true;
ClearDialogImage();
EndDialog(IDOK);
return false;
case ID_CANCEL:
ClearDialogImage();
EndDialog(IDCANCEL);
return false;
/*
* reset params to default
*/
case ID_RESET:
m_nInitGameSpeed = DEFAULT_GAME_SPEED;
m_nInitArcherLevel = DEFAULT_ARCHER_LEVEL;
m_nInitNumLives = DEFAULT_LIVES;
m_nInitNumBadGuys = DEFAULT_BADGUYS;
PutDlgData();
break;
default:
break;
}
}
return CBmpDialog::OnCommand(wParam, lParam);
}
void CUserCfgDlg::OnHScroll(unsigned int nSBCode, unsigned int nPos, CScrollBar *pScroll) {
char szBuf[40];
CDC *pDC;
// can't access a null pointer
assert(pScroll != nullptr);
switch (pScroll->GetDlgCtrlID()) {
case IDS_GAMESPEED:
switch (nSBCode) {
case SB_LEFT:
m_nInitGameSpeed = SPEED_MIN;
break;
case SB_LINELEFT:
case SB_PAGELEFT:
if (m_nInitGameSpeed > SPEED_MIN)
m_nInitGameSpeed--;
break;
case SB_RIGHT:
m_nInitGameSpeed = SPEED_MAX;
break;
case SB_LINERIGHT:
case SB_PAGERIGHT:
if (m_nInitGameSpeed < SPEED_MAX)
m_nInitGameSpeed++;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_nInitGameSpeed = nPos;
break;
default:
break;
}
assert(m_nInitGameSpeed >= SPEED_MIN && m_nInitGameSpeed <= SPEED_MAX);
pScroll->SetScrollPos(m_nInitGameSpeed);
pDC = GetDC();
m_pTxtSpeedSetting->DisplayString(pDC, apszSpeeds[m_nInitGameSpeed - 1], 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
break;
case IDS_LIVES:
switch (nSBCode) {
case SB_BOTTOM:
m_nInitNumLives = LIVES_MIN;
break;
case SB_LINELEFT:
case SB_PAGELEFT:
if (m_nInitNumLives > LIVES_MIN)
m_nInitNumLives--;
break;
case SB_TOP:
m_nInitNumLives = LIVES_MAX;
break;
case SB_LINERIGHT:
case SB_PAGERIGHT:
if (m_nInitNumLives < LIVES_MAX)
m_nInitNumLives++;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_nInitNumLives = nPos;
break;
default:
break;
}
assert(m_nInitNumLives >= LIVES_MIN && m_nInitNumLives <= LIVES_MAX);
pScroll->SetScrollPos(m_nInitNumLives);
pDC = GetDC();
Common::sprintf_s(szBuf, "Lives: %d", m_nInitNumLives);
m_pTxtLives->DisplayString(pDC, szBuf, 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
break;
case IDS_ARCHER_LEVEL:
switch (nSBCode) {
case SB_BOTTOM:
m_nInitArcherLevel = LEVEL_MIN;
break;
case SB_LINELEFT:
case SB_PAGELEFT:
if (m_nInitArcherLevel > LEVEL_MIN)
m_nInitArcherLevel--;
break;
case SB_TOP:
m_nInitArcherLevel = LEVEL_MAX;
break;
case SB_LINERIGHT:
case SB_PAGERIGHT:
if (m_nInitArcherLevel < LEVEL_MAX)
m_nInitArcherLevel++;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_nInitArcherLevel = nPos;
break;
default:
break;
}
assert(m_nInitArcherLevel >= LEVEL_MIN && m_nInitArcherLevel <= LEVEL_MAX);
pScroll->SetScrollPos(m_nInitArcherLevel);
pDC = GetDC();
Common::sprintf_s(szBuf, "Level: %d", m_nInitArcherLevel);
m_pTxtLevel->DisplayString(pDC, szBuf, 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
break;
default:
assert(0);
break;
}
}
bool CUserCfgDlg::OnInitDialog() {
CRect tmpRect;
CDC *pDC;
int nVal;
CBmpDialog::OnInitDialog();
m_bShouldSave = false;
// Get the game speed (1..10)
//
nVal = GetPrivateProfileInt(INI_SECTION, "GameSpeed", DEFAULT_GAME_SPEED, INI_FILENAME);
m_nInitGameSpeed = nVal;
if (nVal < SPEED_MIN || nVal > SPEED_MAX)
m_nInitGameSpeed = DEFAULT_GAME_SPEED;
// Get the Archer level (1..8)
//
nVal = GetPrivateProfileInt(INI_SECTION, "ArcherLevel", DEFAULT_ARCHER_LEVEL, INI_FILENAME);
m_nInitArcherLevel = nVal;
if (nVal < LEVEL_MIN || nVal > LEVEL_MAX)
m_nInitArcherLevel = DEFAULT_ARCHER_LEVEL;
// Get initial number of lives (1..5)
//
nVal = GetPrivateProfileInt(INI_SECTION, "NumberOfLives", DEFAULT_LIVES, INI_FILENAME);
m_nInitNumLives = nVal;
if (nVal < LIVES_MIN || nVal > LIVES_MAX)
m_nInitNumLives = DEFAULT_LIVES;
// Get initial number of badguys
//
nVal = GetPrivateProfileInt(INI_SECTION, "NumberOfBadGuys", DEFAULT_BADGUYS, INI_FILENAME);
m_nInitNumBadGuys = nVal;
if (nVal < BADGUYS_MIN || nVal > BADGUYS_MAX)
m_nInitNumBadGuys = DEFAULT_BADGUYS;
MFC::SetScrollRange(GetDlgItem(IDS_GAMESPEED)->m_hWnd, SB_CTL, SPEED_MIN, SPEED_MAX, true);
MFC::SetScrollRange(GetDlgItem(IDS_LIVES)->m_hWnd, SB_CTL, LIVES_MIN, LIVES_MAX, true);
MFC::SetScrollRange(GetDlgItem(IDS_ARCHER_LEVEL)->m_hWnd, SB_CTL, LEVEL_MIN, LEVEL_MAX, true);
pDC = GetDC();
tmpRect.SetRect(18, 113, 65, 132);
m_pTxtSpeed = new CText;
m_pTxtSpeed->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
tmpRect.SetRect(66, 113, 200, 132);
m_pTxtSpeedSetting = new CText;
m_pTxtSpeedSetting->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
tmpRect.SetRect(18, 25, 68, 42);
m_pTxtLevel = new CText;
m_pTxtLevel->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
tmpRect.SetRect(18, 66, 68, 83);
m_pTxtLives = new CText;
m_pTxtLives->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
ReleaseDC(pDC);
if ((pOKButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pOKButton).SetPalette(m_pPalette); // set the palette to use
(*pOKButton).SetControl(ID_OK, this); // tie to the dialog control
}
if ((pCancelButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pCancelButton).SetPalette(m_pPalette); // set the palette to use
(*pCancelButton).SetControl(ID_CANCEL, this); // tie to the dialog control
}
if ((pDefaultsButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pDefaultsButton).SetPalette(m_pPalette); // set the palette to use
(*pDefaultsButton).SetControl(ID_RESET, this); // tie to the dialog control
}
return true;
}
void CUserCfgDlg::OnPaint() {
CDC *pDC;
CBmpDialog::OnPaint();
PutDlgData();
pDC = GetDC();
m_pTxtSpeed->DisplayString(pDC, "Speed:", 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
}
void CUserCfgDlg::OnDestroy() {
ClearDialogImage();
assert(m_pTxtSpeed != nullptr);
if (m_pTxtSpeed != nullptr) {
delete m_pTxtSpeed;
m_pTxtSpeed = nullptr;
}
assert(m_pTxtSpeedSetting != nullptr);
if (m_pTxtSpeedSetting != nullptr) {
delete m_pTxtSpeedSetting;
}
assert(m_pTxtLevel != nullptr);
if (m_pTxtLevel != nullptr) {
delete m_pTxtLevel;
}
assert(m_pTxtLives != nullptr);
if (m_pTxtLives != nullptr) {
delete m_pTxtLives;
}
if (m_bShouldSave) {
WritePrivateProfileString(INI_SECTION, "GameSpeed", Common::String::format("%d", m_nInitGameSpeed).c_str(), INI_FILENAME);
WritePrivateProfileString(INI_SECTION, "ArcherLevel", Common::String::format("%d", m_nInitArcherLevel).c_str(), INI_FILENAME);
WritePrivateProfileString(INI_SECTION, "NumberOfLives", Common::String::format("%d", m_nInitNumLives).c_str(), INI_FILENAME);
WritePrivateProfileString(INI_SECTION, "NumberOfBadGuys", Common::String::format("%d", m_nInitNumBadGuys).c_str(), INI_FILENAME);
}
CBmpDialog::OnDestroy();
}
void CUserCfgDlg::ClearDialogImage() {
if (pOKButton != nullptr) { // release the button
delete pOKButton;
pOKButton = nullptr;
}
if (pCancelButton != nullptr) { // release the button
delete pCancelButton;
pCancelButton = nullptr;
}
if (pDefaultsButton != nullptr) { // release the button
delete pDefaultsButton;
pDefaultsButton = nullptr;
}
ValidateRect(nullptr);
}
BEGIN_MESSAGE_MAP(CUserCfgDlg, CBmpDialog)
ON_WM_CLOSE()
ON_WM_HSCROLL()
ON_WM_PAINT()
ON_WM_DESTROY()
END_MESSAGE_MAP()
} // namespace Archeroids
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,84 @@
/* 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 HODJNPODJ_ARCHEROIDS_USERCFG_H
#define HODJNPODJ_ARCHEROIDS_USERCFG_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
namespace Bagel {
namespace HodjNPodj {
namespace Archeroids {
#define IDD_USERCFG 100
#define DEFAULT_GAME_SPEED 4
#define DEFAULT_ARCHER_LEVEL 1
#define DEFAULT_LIVES 3
#define DEFAULT_BADGUYS 16
#define SPEED_MIN 1
#define SPEED_MAX 10
#define LEVEL_MIN 1
#define LEVEL_MAX 8
#define LIVES_MIN 1
#define LIVES_MAX 5
#define BADGUYS_MIN 1
#define BADGUYS_MAX 16
class CUserCfgDlg : public CBmpDialog {
public:
CUserCfgDlg(CWnd *, CPalette *, unsigned int);
protected:
virtual bool OnCommand(WPARAM, LPARAM) override;
virtual bool OnInitDialog() override;
void PutDlgData();
void ClearDialogImage();
void OnDestroy();
void OnHScroll(unsigned int, unsigned int, CScrollBar *);
void OnPaint();
DECLARE_MESSAGE_MAP()
//
// user preference data
//
CText *m_pTxtSpeed = nullptr;
CText *m_pTxtSpeedSetting = nullptr;
CText *m_pTxtLevel = nullptr;
CText *m_pTxtLives = nullptr;
int m_nInitGameSpeed = 0;
int m_nInitArcherLevel = 0;
int m_nInitNumLives = 0;
int m_nInitNumBadGuys = 0;
bool m_bShouldSave = false; // True if we should save theses settings
};
} // namespace Archeroids
} // namespace HodjNPodj
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
/* 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 HODJNPODJ_ARTPARTS_ARTPARTS_H
#define HODJNPODJ_ARTPARTS_ARTPARTS_H
#include "bagel/boflib/sound.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
namespace Bagel {
namespace HodjNPodj {
namespace ArtParts {
// Border info
#define SIDE_BORDER 20
#define TOP_BORDER 28 //32
#define BOTTOM_BORDER 20 //16
#define HILITE_BORDER 3
// Art Parts constants
#define ART_WIDTH 600
#define ART_HEIGHT 432
// For the "frame" of correct pieces around the artwork:
#define FRAME_WIDTH 4
#define FRAME_HEIGHT 4
// Starting value defaults
#define MAX_COLUMNS 30
#define MIN_COLUMNS 1
#define MAX_ROWS 24
#define MIN_ROWS 1
#define START_COLUMNS 4
#define START_ROWS 4
// Timer constants
#define MIN_TIME 0 // 15 Seconds
#define MAX_TIME 600 // 180 Seconds = 3 minute max
#define TIMER_START 0 // Increment scrollbar in steps of 15 Secs
#define TIMER_MAX 12 // if Time > MAX_TIME, No Time Limit
#define DISPLAY_TIMER 1
#define SHOW_TIMER 2
#define MS_SCALE 1000 // Scale seconds to milliseconds
#define CLICK_TIME 1000 // Every Second, update timer clock
#define PAUSE_TIME 3000 // Wait three seconds before erasing hint screen
// Sound files
#define PICK_SOUND ".\\sound\\pickart.wav"
#define SWITCH_SOUND ".\\sound\\moveart.wav"
#define WIN_SOUND ".\\sound\\sound146.wav"
#define UNDO_SOUND ".\\sound\\sound355.wav"
#define LOSE_SOUND ".\\sound\\buzzer.wav"
#define RULES_WAV ".\\sound\\artparts.wav"
#define GAME_THEME ".\\sound\\artparts.mid"
// Backdrop bitmaps
#define MAINSCREEN ".\\ART\\ARTPART1.BMP"
#define FRAMESCREEN ".\\ART\\ARTPART1.BMP"
#define TEXTSCREEN ".\\ART\\ARTTEMP.BMP"
#define DATA_FILE "artfiles.dat"
#define MAX_FILE_LENGTH 20 // Longest Art file name length allowed
// New Game button area
#define NEWGAME_LOCATION_X 70
#define NEWGAME_LOCATION_Y 5
#define NEWGAME_WIDTH 113
#define NEWGAME_HEIGHT 13
// Time Display area
#define TIME_LOCATION_X 457
#define TIME_LOCATION_Y 4
#define TIME_WIDTH 117
#define TIME_HEIGHT 16
/////////////////////////////////////////////////////////////////////////////
// CMainWindow:
// See game.cpp for the code to the member functions and the message map.
//
class CMainWindow : public CFrameWnd {
public:
CMainWindow();
~CMainWindow();
bool LoadArtWork();
void DrawPart(const CPoint &Src, const CPoint &Dst, int nWidth, int nHeight);
void SwitchAreas(const CRect &Src, const CRect &Dst);
void InitValues();
void NewGame();
void CheckForWin();
void ShowOutOfPlace();
//added data members:
bool m_bPlaying = false; // Flag True if playing, False if setting options
bool m_bNewGame = false; // Flag to check if a new game is being played
bool m_bFirst = false; // Flag to check if the first area is being selected
CPoint First;
CPoint Second;
CPoint Center;
CPoint UpLeft;
CRect BaseRect; // The part that is the base of the select area
CRect OldRect; // The last area highlighted
CRect HiLiteRect; // The new area to highlight
CRect SrcRect; // The area to be moved
CRect DstRect; // The destination of the moving area
void SplashScreen();
void SplashScratch();
void SplashScratchPaint();
private:
POINT Grid[MAX_COLUMNS][MAX_ROWS]; // Location of the art parts
CBmpButton *m_pScrollButton = nullptr;
CBitmap *pScratch1 = nullptr, // Off-screen bitmap of current positions
*pScratch2 = nullptr, // Off-screen bitmap of new positions
*pOldBmp1 = nullptr,
*pOldBmp2 = nullptr;
CPalette *pOldPal1 = nullptr,
*pOldPal2 = nullptr;
CDC *pScratch1DC = nullptr,
*pScratch2DC = nullptr;
CText *m_pTimeText = nullptr; // Time to be posted in Locale box of screen
CBitmap *pLocaleBitmap = nullptr, // Locale of game bitmap for title bar
*pBlankBitmap = nullptr; // Blank area of locale for time display
bool bStartOkay = true;
bool bGameStarted = false; // becomes true at start time, false at game end
bool bSwitched = false; // flag for undo -- only true after a part switch
bool bSuccess;
bool m_bIgnoreScrollClick;
bool m_bShowOutOfPlace = false;
char szCurrentArt[64] = {};
static CPalette *pGamePalette; // Palette of current artwork
static int nSeconds;
static int nMinutes;
static int nLastPick;
static int m_nTime; // Time is in SECONDS
static int m_nRows; // Number of rows in the artwork grid
static int m_nColumns; // Number of columns in the artwork grid
static int m_nWidth; // The Width of each Part
static int m_nHeight; // The Height of each Part
static float m_nScore; // The current percentage of correctly placed parts
static bool bFramed; // Framed (hint) mode is turned off by default
static int tempTime; // temporary holding places
static int tempRows; //...for options changes,
static int tempColumns; //...which only get used
static bool tempFramed; //...when NewGame is called.
CSound *pGameSound = nullptr; // Game theme song
private:
void initStatics();
void OnSoundNotify(CSound *pSound);
static bool CopyPaletteContents(CPalette *pSource, CPalette *pDest);
void MyFocusRect(CDC *pDC, CRect rect, int nDrawMode);
static void GetSubOptions(CWnd *pParentWind);
protected:
virtual bool OnCommand(WPARAM wParam, LPARAM lParam) override;
//{{AFX_MSG( CMainWindow )
afx_msg void OnPaint();
afx_msg void OnChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags);
afx_msg void OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags);
afx_msg void OnTimer(uintptr nIDEvent);
afx_msg void OnLButtonDown(unsigned int nFlags, CPoint point);
afx_msg void OnRButtonDown(unsigned int nFlags, CPoint point);
afx_msg void OnLButtonUp(unsigned int nFlags, CPoint point);
afx_msg void OnMButtonDown(unsigned int nFlags, CPoint point);
afx_msg void OnMouseMove(unsigned int nFlags, CPoint point);
afx_msg void OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags);
afx_msg void OnClose();
afx_msg LRESULT OnMCINotify(WPARAM, LPARAM);
afx_msg LRESULT OnMMIONotify(WPARAM, LPARAM);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
} // namespace ArtParts
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,45 @@
/* 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 HODJNPODJ_ARTPARTS_GLOBALS_H
#define HODJNPODJ_ARTPARTS_GLOBALS_H
namespace Bagel {
namespace HodjNPodj {
namespace ArtParts {
// Main Window positioning constants
#define GAME_WIDTH 640
#define GAME_HEIGHT 480
// Scroll button size and positioning information
#define IDC_SCROLL 850
#define SCROLL_BUTTON_X 250
#define SCROLL_BUTTON_Y 0
#define SCROLL_BUTTON_DX 140
#define SCROLL_BUTTON_DY 23
} // namespace ArtParts
} // namespace HodjNPodj
} // namespace Bagel
#endif

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/>.
*
*/
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "artparts.h"
namespace Bagel {
namespace HodjNPodj {
namespace ArtParts {
HWND FAR PASCAL RunArtp(HWND, LPGAMESTRUCT);
HINSTANCE hDLLInst;
HINSTANCE hExeInst;
LPGAMESTRUCT pGameInfo;
// global the pointer to the your game's main window
HWND ghParentWnd;
/////////////////////////////////////////////////////////////////////////////
// Public C interface
HWND FAR PASCAL RunArtp(HWND hParentWnd, LPGAMESTRUCT lpGameInfo) {
CMainWindow *pMain;
pGameInfo = lpGameInfo;
// invoke your game here by creating a pGame for your main window
// look at the InitInstance for your game for this
ghParentWnd = hParentWnd;
if ((pMain = new CMainWindow) != nullptr) {
// pMain->ShowWindow(SW_SHOWNORMAL);
// pMain->UpdateWindow();
pMain->SetActiveWindow();
}
// these must be set in this function
hDLLInst = (HINSTANCE)GetWindowWord(pMain->m_hWnd, GWW_HINSTANCE);
hExeInst = (HINSTANCE)GetWindowWord(hParentWnd, GWW_HINSTANCE);
return pMain->m_hWnd; // return the m_hWnd of your main game window
}
} // namespace ArtParts
} // namespace HodjNPodj
} // namespace Bagel

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/>.
*
*/
#ifndef HODJNPODJ_ARTPARTS_GAMEDLL_H
#define HODJNPODJ_ARTPARTS_GAMEDLL_H
#include "bagel/afxwin.h"
namespace Bagel {
namespace HodjNPodj {
namespace ArtParts {
/**
*****************************************************************
*
* RunArtp
*
* FUNCTIONAL DESCRIPTION:
*
* This is the API function for the DLL. It is what the calling app
* calls to invoke poker
*
* FORMAL PARAMETERS:
*
* hParentWnd, lpGameInfo
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
***************************************************************
*/
extern HWND FAR PASCAL RunArtp(HWND hParentWnd, LPGAMESTRUCT lpGameInfo);
} // namespace ArtParts
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,378 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
#include "bagel/hodjnpodj/artparts/globals.h"
#include "bagel/hodjnpodj/artparts/resource.h"
#include "bagel/hodjnpodj/artparts/artparts.h"
#include "bagel/hodjnpodj/artparts/optndlg.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
namespace Bagel {
namespace HodjNPodj {
namespace ArtParts {
static CPalette *pSubOptionsPalette;
static CColorButton *pOKButton = nullptr; // OKAY button on scroll
static CColorButton *pCancelButton = nullptr; // Cancel button on scroll
static CCheckButton *pFramedButton = nullptr; // Framed check box
CText *m_pPartsText = nullptr;
CText *m_pColumnText = nullptr;
CText *m_pRowText = nullptr;
CText *m_pTimerText = nullptr;
int m_nColumnFactors[14] = {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 25, 30}; // 14 factors
int m_nRowFactors[11] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24}; // 11 factors
int m_nTimeScale[12] = {15, 30, 45, 60, 75, 90, 120, 180, 240, 300, 600, 700};
/////////////////////////////////////////////////////////////////////////////
// COptnDlg dialog
COptnDlg::COptnDlg(CWnd* pParent, CPalette* pPalette)
: CBmpDialog(pParent, pPalette, IDD_SUBOPTIONS, ".\\ART\\SSCROLL.BMP") {
//{{AFX_DATA_INIT(COptnDlg)
m_nTime = MIN_TIME;
m_nColumns = MIN_COLUMNS;
m_nRows = MIN_ROWS;
m_nNumParts = m_nColumns * m_nRows;
nCFacs = 14;
nRFacs = 11;
m_bFramed = false;
pSubOptionsPalette = pPalette;
//}}AFX_DATA_INIT
}
COptnDlg::~COptnDlg() {
if (m_pPartsText != nullptr)
delete m_pPartsText;
if (m_pColumnText != nullptr)
delete m_pColumnText;
if (m_pRowText != nullptr)
delete m_pRowText;
if (m_pTimerText != nullptr)
delete m_pTimerText;
// if( m_pFramedText != nullptr )
// delete m_pFramedText;
CBmpDialog::OnDestroy();
}
void COptnDlg::DoDataExchange(CDataExchange* pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COptnDlg)
DDX_Control(pDX, IDC_NUMCOLUMNS, m_ScrollColumns);
DDX_Control(pDX, IDC_NUMROWS, m_ScrollRows);
DDX_Control(pDX, IDC_TIMELIMIT, m_ScrollTime);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COptnDlg, CDialog)
//{{AFX_MSG_MAP(COptnDlg)
ON_WM_HSCROLL()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_BN_CLICKED(IDC_FRAMED, COptnDlg::OnFramed)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COptnDlg message handlers
int COptnDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CBmpDialog::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
bool COptnDlg::OnInitDialog() {
CBmpDialog::OnInitDialog();
int i;
CDC *pDC;
CRect statRect;
pDC = GetDC();
statRect.SetRect(LEFT_SIDE, 45, LEFT_SIDE + 100, 60);
if ((m_pPartsText = new CText()) != nullptr) {
(*m_pPartsText).SetupText(pDC, pSubOptionsPalette, &statRect, JUSTIFY_LEFT);
}
statRect.SetRect(LEFT_SIDE, 65, LEFT_SIDE + 100, 80);
if ((m_pColumnText = new CText()) != nullptr) {
(*m_pColumnText).SetupText(pDC, pSubOptionsPalette, &statRect, JUSTIFY_LEFT);
}
m_ScrollColumns.SetScrollRange(0, nCFacs - 1, 0); // Array starts at zero, so
for (i = 0; i < nCFacs; i++) {
if (m_nColumnFactors[i] == m_nColumns)
m_ScrollColumns.SetScrollPos(i, true);
}
statRect.SetRect(LEFT_SIDE, 99, LEFT_SIDE + 100, 114);
if ((m_pRowText = new CText()) != nullptr) {
(*m_pRowText).SetupText(pDC, pSubOptionsPalette, &statRect, JUSTIFY_LEFT);
}
m_ScrollRows.SetScrollRange(0, nRFacs - 1, 0); //...last element is Max - 1
for (i = 0; i < nRFacs; i++) {
if (m_nRowFactors[i] == m_nRows)
m_ScrollRows.SetScrollPos(i, true);
}
m_nNumParts = m_nColumns * m_nRows;
statRect.SetRect(LEFT_SIDE, 132, LEFT_SIDE + 100, 146);
if ((m_pTimerText = new CText()) != nullptr) {
(*m_pTimerText).SetupText(pDC, pSubOptionsPalette, &statRect, JUSTIFY_LEFT);
}
m_ScrollTime.SetScrollRange(TIMER_START, TIMER_MAX - 1, 0);
if (m_nTime == 0) m_nTime = m_nTimeScale[TIMER_MAX - 1];
for (i = 0; i < TIMER_MAX; i++) {
if (m_nTimeScale[i] == m_nTime)
m_ScrollTime.SetScrollPos(i, true);
}
ReleaseDC(pDC);
statRect.SetRect(155, 45, 205, 60);
if ((pOKButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pOKButton).SetPalette(pSubOptionsPalette); // set the palette to use
(*pOKButton).SetControl(IDOK, this); // tie to the dialog control
}
if ((pCancelButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pCancelButton).SetPalette(pSubOptionsPalette); // set the palette to use
(*pCancelButton).SetControl(IDCANCEL, this); // tie to the dialog control
}
if ((pFramedButton = new CCheckButton) != nullptr) { // build a color QUIT button to let us exit
(*pFramedButton).SetPalette(pSubOptionsPalette); // set the palette to use
(*pFramedButton).SetControl(IDC_FRAMED, this); // tie to the dialog control
}
((CWnd *)this)->CheckDlgButton(IDC_FRAMED, m_bFramed); // Set the frame option box
return true; // return true unless you set the focus to a control
}
bool COptnDlg::OnEraseBkgnd(CDC *pDC) {
return true;
}
void COptnDlg::OnDestroy() {
CBmpDialog::OnDestroy();
}
void COptnDlg::OnHScroll(unsigned int nSBCode, unsigned int nPos, CScrollBar* pScrollBar) {
int pMin,
pMax;
int OldPos = pScrollBar->GetScrollPos();
int NewPos = OldPos;
pScrollBar->GetScrollRange(&pMin, &pMax);
switch (nSBCode) {
case SB_LINERIGHT:
case SB_PAGERIGHT:
NewPos ++;
break;
case SB_RIGHT:
NewPos = pMax;
break;
case SB_LINELEFT:
case SB_PAGELEFT:
NewPos--;
break;
case SB_LEFT:
NewPos = pMin;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
NewPos = nPos;
break;
}
if (NewPos < pMin) NewPos = pMin;
if (NewPos > pMax) NewPos = pMax;
if (NewPos != OldPos) { //To prevent "flicker"
(*pScrollBar).SetScrollPos(NewPos, true); //...only update when
} //...changed
UpdateScrollbars();
CDialog::OnHScroll(nSBCode, NewPos, pScrollBar);
}
/*****************************************************************
*
* UpdateScrollbars
*
* FUNCTIONAL DESCRIPTION:
*
* Updates data adjusted with scrollbars
*
* FORMAL PARAMETERS:
*
* none
*
* IMPLICIT INPUT PARAMETERS:
*
* CScrollbar pScrollTime, pScrollColumns, pScrollRows
*
* IMPLICIT OUTPUT PARAMETERS:
*
* int m_nTime, m_nNumParts, m_nColumns, m_nRows
*
* RETURN VALUE:
*
* void
*
****************************************************************/
void COptnDlg::UpdateScrollbars() {
int OldValue;
CDC *pDC;
char msg[64];
int nMins, nSecs;
pDC = GetDC();
OldValue = m_nTime;
m_nTime = m_nTimeScale[m_ScrollTime.GetScrollPos()];
if (OldValue != m_nTime) {
if (m_nTime == m_nTimeScale[TIMER_MAX - 1])
Common::sprintf_s(msg, "Time Limit: None");
else {
nMins = m_nTime / 60;
nSecs = m_nTime % 60;
Common::sprintf_s(msg, "Time Limit: %02d:%02d", nMins, nSecs);
}
(*m_pTimerText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
}
OldValue = m_nColumns;
m_nColumns = m_nColumnFactors[m_ScrollColumns.GetScrollPos()];
if (OldValue != m_nColumns) {
Common::sprintf_s(msg, "Columns: %d", m_nColumns);
(*m_pColumnText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
}
OldValue = m_nRows;
m_nRows = m_nRowFactors[m_ScrollRows.GetScrollPos()];
if (OldValue != m_nRows) {
Common::sprintf_s(msg, "Rows: %d", m_nRows);
(*m_pRowText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
}
OldValue = m_nNumParts;
m_nNumParts = m_nColumns * m_nRows;
if (OldValue != m_nNumParts) {
Common::sprintf_s(msg, "Parts: %d", m_nNumParts);
(*m_pPartsText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
}
ReleaseDC(pDC);
}
void COptnDlg::OnFramed() {
m_bFramed = !m_bFramed;
((CWnd *)this)->CheckDlgButton(IDC_FRAMED, m_bFramed);
}
void COptnDlg::OnOK() {
if (m_nTime > MAX_TIME) m_nTime = MIN_TIME;
ClearDialogImage();
EndDialog(IDOK);
}
void COptnDlg::OnCancel() {
ClearDialogImage();
EndDialog(0);
}
void COptnDlg::OnPaint() {
CDC *pDC;
char msg[64];
int nMins, nSecs;
CBmpDialog::OnPaint();
pDC = GetDC();
Common::sprintf_s(msg, "Parts: %d", m_nNumParts);
(*m_pPartsText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
Common::sprintf_s(msg, "Columns: %d", m_nColumns);
(*m_pColumnText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
Common::sprintf_s(msg, "Rows: %d", m_nRows);
(*m_pRowText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
if (m_nTime == m_nTimeScale[TIMER_MAX - 1])
Common::sprintf_s(msg, "Time Limit: None");
else {
nMins = m_nTime / 60;
nSecs = m_nTime % 60;
Common::sprintf_s(msg, "Time Limit: %02d:%02d", nMins, nSecs);
}
(*m_pTimerText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
ReleaseDC(pDC);
}
void COptnDlg::ClearDialogImage() {
if (pOKButton != nullptr) { // release the button
delete pOKButton;
pOKButton = nullptr;
}
if (pCancelButton != nullptr) { // release the button
delete pCancelButton;
pCancelButton = nullptr;
}
if (pFramedButton != nullptr) { // release the button
delete pFramedButton;
pFramedButton = nullptr;
}
ValidateRect(nullptr);
}
} // namespace ArtParts
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,89 @@
/* 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 HODJNPODJ_ARTPARTS_OPTNDLG_H
#define HODJNPODJ_ARTPARTS_OPTNDLG_H
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
namespace Bagel {
namespace HodjNPodj {
namespace ArtParts {
#define LEFT_SIDE 30
#define OPTIONS_COLOR RGB(0, 0, 0) // Color of the stats info CText
/////////////////////////////////////////////////////////////////////////////
// COptnDlg dialog
class COptnDlg : public CBmpDialog {
// Construction
public:
COptnDlg(CWnd* pParent = nullptr, CPalette *pPalette = nullptr); // standard constructor
~COptnDlg(); // destructor
void UpdateScrollbars();
void ClearDialogImage();
int m_nTime = 0;
int m_nRows = 0;
int m_nColumns = 0;
int m_nMins = 0;
int m_nSecs = 0;
float m_nScore = 0.0;
bool m_bFramed = false;
int m_nNumParts = 0;
int nCFacs = 0;
int nRFacs = 0;
// Dialog Data
//{{AFX_DATA(COptnDlg)
enum { IDD = IDD_SUBOPTIONS };
CScrollBar m_ScrollTime;
CScrollBar m_ScrollColumns;
CScrollBar m_ScrollRows;
//}}AFX_DATA
// Implementation
protected:
virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support
// Generated message map functions
//{{AFX_MSG(COptnDlg)
virtual bool OnInitDialog() override;
afx_msg void OnHScroll(unsigned int nSBCode, unsigned int nPos, CScrollBar* pScrollBar);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg bool OnEraseBkgnd(CDC *pDC);
virtual void OnOK() override;
virtual void OnCancel() override;
afx_msg void OnPaint();
afx_msg void OnFramed();
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
} // namespace ArtParts
} // namespace HodjNPodj
} // namespace Bagel
#endif

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 HODJNPODJ_ARTPARTS_RESOURCE_H
#define HODJNPODJ_ARTPARTS_RESOURCE_H
namespace Bagel {
namespace HodjNPodj {
namespace ArtParts {
//{{NO_DEPENDENCIES}}
// App Studio generated include file.
// Used by GAME.RC
//
#define IDD_SUBOPTIONS 115
//#define IDB_LOCALE_BMP 301
#define IDC_RULES 1002
#define IDC_NUMCOLUMNS 1021
#define IDC_NUMROWS 1022
#define IDC_TIMELIMIT 1023
#define IDC_FRAMED 1025
} // namespace ArtParts
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,266 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/boflib/misc.h"
#include "bagel/hodjnpodj/barbershop/main.h"
#include "bagel/hodjnpodj/barbershop/animate.h"
#include "bagel/hodjnpodj/hodjnpodj.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
// globals!!
//
//
extern CPalette *pGamePalette;
extern LPGAMESTRUCT pGameParams;
CAnimate::CAnimate(CSound *pSound) {
m_pSprite = nullptr;
m_cClownRect = CRect(CLOWN_LEFT, CLOWN_TOP, CLOWN_RIG, CLOWN_BOT);
m_cUFORect = CRect(UFO_LEFT, UFO_TOP, UFO_RIG, UFO_BOT);
m_cCarRect = CRect(CAR_LEFT, CAR_TOP, CAR_RIG, CAR_BOT);
m_cBratRect = CRect(BRAT_LEFT, BRAT_TOP, BRAT_RIG, BRAT_BOT);
m_cLolliRect = CRect(LOLLI_LEFT, LOLLI_TOP, LOLLI_RIG, LOLLI_BOT);
m_cCutRect = CRect(CUT_LEFT, CUT_TOP, CUT_RIG, CUT_BOT);
m_pSound = pSound;
//srand((unsigned) time(nullptr)); // seed the random number generator
} // CAnimate
CAnimate::~CAnimate() {
} // ~CAnimate
bool CAnimate::Clown(CDC *pDC, CPoint point) {
bool bSuccess;
int i;
if (m_cClownRect.PtInRect(point) == false)
return false;
m_pSprite = new CSprite;
(*m_pSprite).SharePalette(pGamePalette);
bSuccess = (*m_pSprite).LoadCels(pDC, CLOWN_BMP, CLOWN_FRAMES);
ASSERT(bSuccess);
(*m_pSprite).SetMasked(false);
(*m_pSprite).SetMobile(false);
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
CLOWN_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
} // end if
if (bSuccess == true) {
(*m_pSprite).SetCel(CLOWN_FRAMES);
for (i = 0; i < CLOWN_FRAMES - 1; i++) {
(*m_pSprite).PaintSprite(
pDC,
m_cClownRect.TopLeft()
);
Sleep(CLOWN_TIME_SLICE);
} // end for
} // end if
m_pSprite->EraseSprite(pDC);
delete m_pSprite;
m_pSprite = nullptr;
return true;
}
bool CAnimate::UFO(CDC *pDC, CPoint point) {
bool bSuccess;
int i;
if (m_cCarRect.PtInRect(point) == false)
return false;
m_pSprite = new CSprite;
(*m_pSprite).SharePalette(pGamePalette);
bSuccess = (*m_pSprite).LoadCels(pDC, UFOA_BMP, UFOA_FRAMES);
ASSERT(bSuccess);
(*m_pSprite).SetMasked(false);
(*m_pSprite).SetMobile(false);
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
SPACESHIP_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
} // end if
if (bSuccess == true) {
int j;
(*m_pSprite).SetCel(UFOA_FRAMES);
for (i = 0; i < 8; i++) {
(*m_pSprite).PaintSprite(
pDC,
m_cUFORect.TopLeft()
);
Sleep(UFOA_TIME_SLICE);
} // end for
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
SPACERAY_WAV,
SOUND_WAVE
);
m_pSound->play();
m_pSound->initialize(
SPACESHIP_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
} // end if
for (j = i; j < UFOA_FRAMES - 1; j++) {
(*m_pSprite).PaintSprite(
pDC,
m_cUFORect.TopLeft()
);
Sleep(UFOA_TIME_SLICE);
} // end for
} // end if
Sleep(UFO_PAUSE); // pause for a few seconds between animations
bSuccess = (*m_pSprite).LoadCels(pDC, UFOB_BMP, UFOB_FRAMES);
ASSERT(bSuccess);
(*m_pSprite).SetMasked(false);
(*m_pSprite).SetMobile(false);
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
SPACESHIP_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
} // end if
if (bSuccess == true) {
int j;
(*m_pSprite).SetCel(UFOB_FRAMES);
for (i = 0; i < 9; i++) {
(*m_pSprite).PaintSprite(
pDC,
m_cUFORect.TopLeft()
);
Sleep(UFOB_TIME_SLICE);
} // end for
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize( // play synchronous beam up sound
SPACERAY_WAV,
SOUND_WAVE
);
m_pSound->play();
m_pSound->initialize( // async space ship sound
SPACESHIP_WAV,
SOUND_WAVE | SOUND_QUEUE | SOUND_ASYNCH
);
m_pSound->play();
} // end if
for (j = i; j < UFOB_FRAMES - 1; j++) {
(*m_pSprite).PaintSprite(
pDC,
m_cUFORect.TopLeft()
);
Sleep(UFOB_TIME_SLICE);
} // end for
} // end if
m_pSprite->EraseSprite(pDC);
delete m_pSprite;
m_pSprite = nullptr;
return true;
}
bool CAnimate::Brat(CPoint point) {
if (m_cBratRect.PtInRect(point) == false)
return false;
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
BRAT_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
} // end if
return true;
} // Brat
bool CAnimate::Lollipop(CPoint point) {
if (m_cLolliRect.PtInRect(point) == false)
return false;
if (pGameParams->bSoundEffectsEnabled == false)
return true;
if ((brand() % 2) == 0) { // randomly chose sound wave to play
m_pSound->initialize(
LOLLI_A_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
} else {
m_pSound->initialize(
LOLLI_B_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
} // end if
m_pSound->play();
return true;
} // Lollipop
bool CAnimate::Haircut(CPoint point) {
if (m_cCutRect.PtInRect(point) == false)
return false;
if (pGameParams->bSoundEffectsEnabled == false)
return true;
m_pSound->initialize(
CUT_WAV,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
return true;
} // Haircut
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,135 @@
/* 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 HODJNPODJ_BARBERSHOP_ANIMATE_H
#define HODJNPODJ_BARBERSHOP_ANIMATE_H
#include "bagel/hodjnpodj/hnplibs/sprite.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
//
// animation sounds
//
#define CLOWN_WAV ".\\sound\\horns.wav"
#define SPACESHIP_WAV ".\\sound\\spaceshp.wav"
#define SPACERAY_WAV ".\\sound\\spaceray.wav"
#define CUT_WAV ".\\sound\\haircut.wav"
#define BRAT_WAV ".\\sound\\doneyet.wav"
#define LOLLI_A_WAV ".\\sound\\lollipop.wav"
#define LOLLI_B_WAV ".\\sound\\hairpop.wav"
//
// Clown animation
//
#define CLOWN_BMP ".\\art\\gum.bmp"
#define CLOWN_FRAMES 24 // Clown morph frames
#define CLOWN_BMP_HEI 96 // demensions of clown art
#define CLOWN_BMP_WID 110
#define CLOWN_LEFT 16 // demensions of clown rect
#define CLOWN_TOP 27
#define CLOWN_RIG (CLOWN_LEFT + CLOWN_BMP_HEI)
#define CLOWN_BOT (CLOWN_TOP + CLOWN_BMP_WID)
#define CLOWN_TIME_SLICE 1 // millisecs, pause between animation cells
//
// UFO beam up animation
//
#define UFOA_BMP ".\\art\\ufo1a.bmp"
#define UFOB_BMP ".\\art\\ufo1b.bmp"
#define UFOA_FRAMES 16 // UFOa frames
#define UFOB_FRAMES 14 // UFOa frames
#define UFO_BMP_HEI 198 // demensions of UFO art
#define UFO_BMP_WID 123
#define UFO_LEFT 134 // demensions of UFO rect
#define UFO_TOP 24
#define UFO_RIG (UFO_LEFT + UFO_BMP_HEI)
#define UFO_BOT (UFO_TOP + UFO_BMP_WID)
#define CAR_LEFT 136 // demensions of race car rect
#define CAR_TOP 116
#define CAR_RIG 228
#define CAR_BOT 145
#define UFOA_TIME_SLICE 1 // millisecs, pause between animation cells
#define UFOB_TIME_SLICE 100 // millisecs, pause between animation cells
#define UFO_PAUSE 1000 // wait a second after stealing the car
//
// Brat effect
//
#define BRAT_LEFT 405
#define BRAT_TOP 24
#define BRAT_RIG 463
#define BRAT_BOT 62
//
// Lollipop effect
//
#define LOLLI_LEFT 472
#define LOLLI_TOP 52
#define LOLLI_RIG 483
#define LOLLI_BOT 59
//
// Haircut effect
//
#define CUT_LEFT 563 //355
#define CUT_TOP 26 //120
#define CUT_RIG 625 //418
#define CUT_BOT 178 //154
class CAnimate {
private: // variables
CSprite *m_pSprite;
CRect m_cClownRect;
CRect m_cUFORect;
CRect m_cCarRect;
CRect m_cBratRect;
CRect m_cLolliRect;
CRect m_cCutRect;
CSound *m_pSound;
public: // functions
CAnimate(CSound*);
~CAnimate();
bool Clown(CDC*, CPoint);
bool UFO(CDC*, CPoint);
bool Brat(CPoint);
bool Lollipop(CPoint);
bool Haircut(CPoint);
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,802 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/cmessbox.h"
#include "bagel/boflib/sound.h"
#include "bagel/hodjnpodj/barbershop/barb.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
//
// global
//
extern LPGAMESTRUCT pGameParams;
/*****************************************************************
*
* CBarber
*
* FUNCTIONAL DESCRIPTION:
*
* Initializes members.
*
* FORMAL PARAMETERS: n/a
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: barbershop quintet object
*
****************************************************************/
CBarber::CBarber(CDC *pDC, CSound *pSound) {
m_cDck = new CDeck();
m_cPnt = new CPaint(pDC);
m_cBrd = new CBoard(m_cPnt);
m_pLogic = new CLogic();
m_pUndo = new CUndo();
m_pSound = pSound;
m_pCrd = nullptr; // remembers cur card
/********************************************************
* Switchs used to prevent further user updates *
* after timer has run out, no moves left, or is solved. *
********************************************************/
m_bIsGameOver = false; // Initialize solved switch
m_bIsWin = false; // Initialize win/lose switch
}
/*****************************************************************
*
* ~Barber
*
* FUNCTIONAL DESCRIPTION:
*
* Destructor
*
* FORMAL PARAMETERS: n/a
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
CBarber::~CBarber() {
if (m_pSound != nullptr) {
m_pSound = nullptr; // never init with a "new" operator
}
if (m_pUndo != nullptr) {
delete m_pUndo;
m_pUndo = nullptr;
}
if (m_pLogic != nullptr) {
delete m_pLogic;
m_pLogic = nullptr;
}
if (m_cBrd != nullptr) {
delete m_cBrd;
m_cBrd = nullptr;
}
if (m_cPnt != nullptr) {
delete m_cPnt;
m_cPnt = nullptr;
}
if (m_cDck != nullptr) {
delete m_cDck;
m_cDck = nullptr;
}
}
/*****************************************************************
*
* NewGame
*
* FUNCTIONAL DESCRIPTION:
*
* Resets interal state, and starts a new game.
*
* FORMAL PARAMETERS:
*
* pDC - device context for painting images to the window.
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
void CBarber::NewGame(CDC *pDC) {
m_cDck->Shuffle();
m_cDck->Deal(m_cBrd);
m_cPnt->Board(pDC, m_cBrd); // paint the cards visually on the board
m_pUndo->Reset(); // clear all undo info
m_bIsGameOver = false; // turn off game over switch
}
/*****************************************************************
*
* Refresh
*
* FUNCTIONAL DESCRIPTION:
*
* Repaints all cards on the board.
*
* FORMAL PARAMETERS: n/a
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
void CBarber::Refresh(CDC *pDC) {
m_cPnt->Refresh(pDC, m_cBrd);
}
/*****************************************************************
*
* OnLButtonDown
*
* FUNCTIONAL DESCRIPTION:
*
* Determines if user clicked on a card or on the undo area.
*
* FORMAL PARAMETERS:
*
* pWnd - the parent window used for poping up message dialog
* boxes.
* pPalette - passed to any message box that needs to be
* displayed.
* point - point where user double clicked.
*
* IMPLICIT INPUT PARAMETERS:
*
* m_pCrd - will remember what card user clicked on.
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
void CBarber::OnLButtonDown(CWnd *pWnd, CPalette *pPalette, CPoint point) {
CDC *pDC = nullptr; // device context for painting
CCard *pCard; // for stack push and pop operations
int i; // index
if ( // user want to undo a change?
m_pUndo->m_cUndoRect.PtInRect(point) == true &&
m_pCrd == nullptr
) {
pDC = pWnd->GetDC();
if (pGameParams->bSoundEffectsEnabled != false)
m_pSound->initialize(
UNDO,
SOUND_WAVE | SOUND_ASYNCH
);
if (m_pUndo->Undo(pDC, m_cBrd, m_cPnt) == true) { // undo successful?
if (pGameParams->bSoundEffectsEnabled != false)
m_pSound->play();
// undoing does not always guarantee there is a move left,
// but it is okay to reset game over switch anyway.
//
m_bIsGameOver = false; // yes - undo successful.
} // end if
pWnd->ReleaseDC(pDC);
return;
} // end if
if (m_bIsGameOver == true)
return;
if ((m_pCrd = m_cPnt->IsOnCard(point)) == nullptr) { // get card corr to point
/********************************************************
* Find out if stock cards need to be recycled. This *
* will occur if the stock card stack is empty and there *
* are cards on the used stack. *
********************************************************/
if (
m_cBrd->GetStack((loc) stock)->m_cRect.PtInRect(point) == true &&
m_cBrd->GetStack((loc) stock)->IsEmpty() == true
) {
int nFlipSnd = 0; // keeps track of when to play fwap sound
pDC = pWnd->GetDC();
// user wants to recycle used stack
//
if (pGameParams->bSoundEffectsEnabled != false) // init sound if it is enabled
m_pSound->initialize(
STOCKCARDS,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
while (m_cBrd->GetStack((loc) used)->IsEmpty() != true) {
pCard = m_cBrd->GetStack((loc) used)->Pop(); // take top card off used stack
m_cBrd->GetStack((loc) stock)->Push(pCard); // put it on stock stack
// sound (if enabled)
if (
pGameParams->bSoundEffectsEnabled != false &&
nFlipSnd % RECYCLE_SOUND_FREQ == 0
)
m_pSound->play(); // make flap sound...
nFlipSnd++; // every three cards
m_cPnt->FlipCard(pDC, pCard); // repaint top card
m_cPnt->Stack(pDC, pCard); // indented on approp stack
} // end while
pWnd->ReleaseDC(pDC); // release device context!
m_pUndo->Reset(); // Can't undo recycled used stack
} // end if
return;
} // end if
/*****************************************************************
* Figure out what stack user clicked on, and behave accordingly. *
*****************************************************************/
switch (m_pCrd->m_pStack->GetID()) {
case fnd: { // foundation stack
/************************************************
* Not allowed to remove cards from foundation. *
* Tell the user his score. *
************************************************/
char buf[32];
Common::sprintf_s(buf, "Score: %d", Score());
CMessageBox cmsgboxScore(
pWnd,
pPalette,
buf
);
m_pCrd = nullptr; // don't remember the clicked card
return;
}
case stock: { // stock stack
/****************************************************
* Flip cards from stock to used stack, or recycle *
* cards on used stack if used stack is empty. *
****************************************************/
CStack *pStock, *pUsed;
pStock = m_cBrd->GetStack(stock); // get stock stack for future ref
pUsed = m_cBrd->GetStack(used); // get used stack too.
// sound (if enabled)
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
STOCKCARDS,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
}
pDC = pWnd->GetDC();
for (i = 0; i < STOCK_DRAW; i++) { // flip over three cards onto used stack
if ((pCard = pStock->Pop()) == nullptr) { // Out of cards on the Stock stack?
break;
}
// Move card from stock stack, to used stack.
//
m_cPnt->FlipCard(pDC, pCard); // give card a flipped sprite
pUsed->Push(pCard); // put stock card on used stack
m_cPnt->Stack(pDC, pCard); // paint card appropriately indented
} // end for
pWnd->ReleaseDC(pDC);
if (pStock->IsEmpty() == true) // game over?
IsGameOver(pWnd);
m_pUndo->Record(i); // note stack flip for possible undoing
m_pCrd = nullptr; // don't remember the clicked card
return;
} // end case
case used: // used stack rules
return; // have fun with these! (no special function)
default: // tab stack
if (m_pCrd->m_bIsBack == true) { // want to flip over card?
pDC = pWnd->GetDC(); // yes
m_cPnt->FlipCard(pDC, m_pCrd); // flip card
m_cPnt->UpdateCard(pDC, m_pCrd); // paint it
pWnd->ReleaseDC(pDC);
m_pUndo->Reset(); // Can't undo flipped card
m_pCrd = nullptr; // don't remember the clicked card
return;
} // end if
} // end switch
}
/*****************************************************************
*
* OnLButtonDblClk
*
* FUNCTIONAL DESCRIPTION:
*
* Handles undo and stock card flips only. Will not remember
* card moving.
*
* FORMAL PARAMETERS:
*
* pWnd - the parent window used for poping up message dialog
* boxes.
* pPalette - passed to any message box that needs to be
* displayed.
* point - point where user double clicked.
*
* IMPLICIT INPUT PARAMETERS:
*
* m_pCrd - will remember what card user clicked on.
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
void CBarber::OnLButtonDblClk(CWnd *pWnd, CPalette *pPalette, CPoint point) {
CDC *pDC = nullptr;
CCard *pCard;
int i;
if ( // user want to undo a change?
m_pUndo->m_cUndoRect.PtInRect(point) == true &&
m_pCrd == nullptr
) {
pDC = pWnd->GetDC();
if (pGameParams->bSoundEffectsEnabled != false)
m_pSound->initialize(
UNDO,
SOUND_WAVE | SOUND_QUEUE
);
if (m_pUndo->Undo(pDC, m_cBrd, m_cPnt) == true) { // undo successful?
if (pGameParams->bSoundEffectsEnabled != false)
m_pSound->play();
m_bIsGameOver = false; // yes
}
pWnd->ReleaseDC(pDC);
return;
} // end if
if (m_bIsGameOver == true)
return;
if ((m_pCrd = m_cPnt->IsOnCard(point)) == nullptr) { // get card corr to point
/********************************************************
* Find out if stock cards need to be recycled. This *
* will occur if the stock card stack is empty and there *
* are cards on the used stack. *
********************************************************/
if (
m_cBrd->GetStack((loc) stock)->m_cRect.PtInRect(point) == true &&
m_cBrd->GetStack((loc) stock)->IsEmpty() == true
) {
int nFlipSnd = 0; // keeps track of when to play fwap sound
// user wants to recycle used stack
//
if (pGameParams->bSoundEffectsEnabled != false) // init sound if it is enabled
m_pSound->initialize(
STOCKCARDS,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
pDC = pWnd->GetDC();
while (m_cBrd->GetStack((loc) used)->IsEmpty() != true) {
pCard = m_cBrd->GetStack((loc) used)->Pop(); // get used card
m_cBrd->GetStack((loc) stock)->Push(pCard); // put used card onto stock
// sound (if enabled)
if ( // play fwap sound...
pGameParams->bSoundEffectsEnabled != false && // every RECYCLE_'_FREQ card
nFlipSnd % RECYCLE_SOUND_FREQ == 0
)
m_pSound->play(); // make flap sound...
nFlipSnd++; // update fwap counter
m_cPnt->FlipCard(pDC, pCard); // change card sprite
m_cPnt->Stack(pDC, pCard); // paint card properly indented on approp stack
} // end while
pWnd->ReleaseDC(pDC);
m_pUndo->Reset(); // Can't undo recycled used stack
} // end if
return;
} // end if
/*****************************************************************
* Figure out what stack user clicked on, and behave accordingly. *
*****************************************************************/
switch (m_pCrd->m_pStack->GetID()) {
case fnd: { // foundation stack rules
/***********************************************
* Not allowed to remove cards from foundation. *
***********************************************/
char buf[32];
Common::sprintf_s(buf, "Score: %d", Score());
CMessageBox cGameOver(
pWnd,
pPalette,
buf
);
m_pCrd = nullptr;
return;
}
case stock: { // stock stack rules
/****************************************************
* Flip cards from stock to used stack, or recycle *
* cards on used stack if used stack is empty. *
****************************************************/
CStack *pStock, *pUsed;
pStock = m_cBrd->GetStack(stock);
pUsed = m_cBrd->GetStack(used);
// sound (if enabled)
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
STOCKCARDS,
SOUND_WAVE | SOUND_ASYNCH | SOUND_QUEUE
);
m_pSound->play();
} // end if
for (i = 0; i < STOCK_DRAW; i++) {
if ((pCard = pStock->Pop()) == nullptr) { // Out of cards on the Stock stack?
break;
}
pDC = pWnd->GetDC();
m_cPnt->FlipCard(pDC, pCard);
pUsed->Push(pCard);
m_cPnt->Stack(pDC, pCard);
pWnd->ReleaseDC(pDC);
} // end for
if (pStock->IsEmpty() == true)
IsGameOver(pWnd);
m_pUndo->Record(i); // note stack flip for possible undoing
m_pCrd = nullptr;
return;
} // end case
default: // tab stacks
if (m_pCrd->m_bIsBack == true) { // user want to flip a card?
pDC = pWnd->GetDC();
m_cPnt->FlipCard(pDC, m_pCrd);
m_cPnt->UpdateCard(pDC, m_pCrd);
pWnd->ReleaseDC(pDC);
m_pUndo->Reset(); // Can't undo flipped card
m_pCrd = nullptr;
return;
} // end if
} // end switch
}
/*****************************************************************
*
* OnMouseMove
*
* FUNCTIONAL DESCRIPTION:
*
* Paint the card at the mouse position if user is holding onto
* a card.
*
* FORMAL PARAMETERS:
*
* pDC - device context for painting images to the window.
*
* IMPLICIT INPUT PARAMETERS:
*
* m_pCrd - contains the card the user is holding.
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
void CBarber::OnMouseMove(CDC *pDC, CPoint point) {
if (m_pCrd == nullptr) // no card selected
return;
m_cPnt->MoveCard(pDC, m_pCrd, point);
}
/*****************************************************************
*
* OnMouseMove
*
* FUNCTIONAL DESCRIPTION:
*
* Paint the card at the mouse position if user is holding onto
* a card.
*
* FORMAL PARAMETERS:
*
* pDC - Device context for painting images on the window.
*
* IMPLICIT INPUT PARAMETERS:
*
* m_pCrd - contains the card the user is holding.
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
void CBarber::OnLButtonUp(CWnd *pWnd) {
CDC *pDC = nullptr;
bool bSuccess = false;
CRect cTest;
CStack *pStack;
int i;
if (m_pCrd == nullptr) // no card selected
return;
/************************************************************
* Updates interal stack reps. Flip thru all stacks. *
* Find card interception on any stack. Adds card to first *
* intercepted stack. *
************************************************************/
for (i = 0; i <= used; i++) {
pStack = m_cBrd->GetStack((loc) i); // get appropriate stack
if (pStack->IsEmpty() == true) { // assigns rect of interest as
cTest = pStack->m_cRect; // either base rect
} else { // or card rect from top of stack
cTest = pStack->Top()->m_pSprite->GetRect();
} // end if
/************************************************************
* Handles special case of current stack is same as *
* stack that the card is in. In this case, either the *
* the rect of previous card (if any) needs to be used as *
* the test region. *
************************************************************/
if (m_pCrd->m_pStack == pStack) { // is card on original stack?
if (m_pCrd->m_pPrevCard != nullptr) { // Yes - any other cards on this stack?
cTest = pStack->Top()->m_pPrevCard->m_pSprite->GetRect();
} else {
cTest = pStack->m_cRect; // either base rect
} // end if
} // end if
/********************************************************
* find out if corner points of the card line anywhere *
* within a stack's rect. *
********************************************************/
//b
if (IsInRect(cTest, m_pCrd->m_pSprite->GetRect()) == false) { //!= true ) { // is card on invalid area?
continue;
} // end if
if (m_pLogic->IsMoveOk(m_pCrd, pStack) == true) {
m_pUndo->Record(m_pCrd->m_pStack, m_pCrd); // note move for possible undoing
m_pCrd->m_pStack->Pop();
pStack->Push(m_pCrd);
bSuccess = true;
} // end if
continue;
//b break;
} // end for
/*************************
* Update visual display. *
*************************/
pDC = (*pWnd).GetDC();
if (bSuccess != true) { // card dropped over stack?
m_cPnt->UpdateCard(pDC, m_pCrd); // no - redraw card over original stack
} else {
m_cPnt->Stack(pDC, m_pCrd); // draw card apro stack
} // end if
(*pWnd).ReleaseDC(pDC);
m_pCrd = nullptr; // clear current card
if (m_cBrd->GetStack(stock)->IsEmpty() == true)
IsGameOver(pWnd); // game over?
}
/*****************************************************************
*
* IsInRect
*
* FUNCTIONAL DESCRIPTION:
*
* Determines if card's hotspot is intercepts the stack rectangle.
*
* FORMAL PARAMETERS:
*
* cStk - The rectangle of the stack.
* cCrd - The rectangle of the card.
*
* IMPLICIT INPUT PARAMETERS:
*
* m_pCrd - it assumes that the user is currently holding a card.
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
bool CBarber::IsInRect(CRect cStk, CRect cCrd) {
//b CPoint point;
CRect inter;
bool bTL;
/*
point.x = cCrd.TopLeft().x + m_pCrd->m_pSprite->GetHotspot().x;
point.y = cCrd.TopLeft().y + m_pCrd->m_pSprite->GetHotspot().y;
*/
//b bTL = cStk.PtInRect(point);
cStk.InflateRect(5, 5);
bTL = inter.IntersectRect(cStk, cCrd);
return bTL;
}
/*****************************************************************
*
* IsGameOver
*
* FUNCTIONAL DESCRIPTION:
*
* Checks every possible move to determine if there are any moves
* left.
*
* FORMAL PARAMETERS: n/a
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
bool CBarber::IsGameOver(CWnd *pWnd) {
/*****************************
* Determine if game is over. *
*****************************/
m_bIsGameOver = m_pLogic->IsGameOver(m_cBrd);
if (m_bIsGameOver == false)
return false;
/**********************
* Determine win/loss. *
**********************/
if (m_cBrd->GetStack((loc) fnd)->Size() == DECK) {
// sound (if enabled)
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
WIN_SOUND,
SOUND_WAVE | SOUND_ASYNCH
);
m_pSound->play();
}
m_bIsWin = true;
} else {
// sound (if enabled)
if (pGameParams->bSoundEffectsEnabled != false) {
m_pSound->initialize(
LOSE_SOUND,
SOUND_WAVE | SOUND_ASYNCH
);
m_pSound->play();
}
m_bIsWin = false;
}
return true;
}
/*****************************************************************
*
* IsNewBack
*
* FUNCTIONAL DESCRIPTION:
*
*
* FORMAL PARAMETERS: n/a
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
bool CBarber::IsNewBack(int nCardBack) {
return m_cPnt->IsNewBack(nCardBack);
}
/*****************************************************************
*
* ChangeBack
*
* FUNCTIONAL DESCRIPTION:
*
*
* FORMAL PARAMETERS: n/a
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
void CBarber::ChangeBack(CDC* pDC, int nCardBack) {
m_cPnt->ChangeBack(pDC, m_cBrd, nCardBack);
}
/*****************************************************************
*
* Score
*
* FUNCTIONAL DESCRIPTION:
*
* Returns number of cards on the foundation, defined as the
* score.
*
* FORMAL PARAMETERS: n/a
*
* IMPLICIT INPUT PARAMETERS: n/a
*
* IMPLICIT OUTPUT PARAMETERS: n/a
*
* RETURN VALUE: n/a
*
****************************************************************/
int CBarber::Score() {
return m_cBrd->GetStack(fnd)->Size();
}
} // namespace Barbershop
} // namespace HodjNPodj
} // 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 HODJNPODJ_BARBERSHOP_BARB_H
#define HODJNPODJ_BARBERSHOP_BARB_H
#include "bagel/hodjnpodj/barbershop/deck.h"
#include "bagel/hodjnpodj/barbershop/board.h"
#include "bagel/hodjnpodj/barbershop/paint.h"
#include "bagel/hodjnpodj/barbershop/logic.h"
#include "bagel/hodjnpodj/barbershop/undo.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/boflib/sound.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define NOT_USED -1
#define USED 0
//
// sounds
//
#define STOCKCARDS ".\\sound\\carddeal.wav"
#define UNDO ".\\sound\\sound355.wav"
#define WIN_SOUND ".\\sound\\applause.wav"
#define LOSE_SOUND ".\\sound\\sosorry.wav"
//
// related to stock card flipping sounds
//
#define RECYCLE_SOUND_FREQ 3
class CBarber {
private:
CDeck *m_cDck = nullptr; // Handles card shuffling
CBoard *m_cBrd = nullptr; // contains position info for all card stacks on screen
CLogic *m_pLogic = nullptr; // determines whether a given move is valid or not
CUndo *m_pUndo = nullptr; // records moves made by user and handles move undoing
CSound *m_pSound = nullptr;
public:
CBarber(CDC*, CSound*);
~CBarber();
void NewGame(CDC*);
void Refresh(CDC*);
void OnLButtonDown(CWnd*, CPalette*, CPoint);
void OnLButtonDblClk(CWnd*, CPalette*, CPoint);
void OnMouseMove(CDC*, CPoint);
void OnLButtonUp(CWnd*);
bool IsInRect(CRect cStk, CRect cCrd);
bool IsGameOver(CWnd*);
bool IsNewBack(int);
void ChangeBack(CDC*, int);
int Score();
CPaint *m_cPnt = nullptr; // used to visually paint cards on screen
CCard *m_pCrd = nullptr; // the card being moved
bool m_bIsGameOver = false; // tells if game has ended
bool m_bIsWin = false; // tells if game was won or lost
};
// Globals!
extern CPalette *pGamePalette;
} // namespace Barbershop
} // namespace HodjNPodj
} // 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/barbershop/board.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
CBoard::CBoard(CPaint *m_cPnt) {
int i;
m_pFound = new CStack(m_cPnt->m_cFound, fnd);
for (i = 0; i < TAB_COUNT; i++)
m_pTab[i] = new CStack(m_cPnt->m_cTab[i], tab + i);
m_pStock = new CStack(m_cPnt->m_cStock, stock);
m_pUsed = new CStack(m_cPnt->m_cUsed, used);
}
CBoard::~CBoard() {
int i;
if (m_pUsed != nullptr) {
delete m_pUsed;
m_pUsed = nullptr;
}
if (m_pStock != nullptr) {
delete m_pStock;
m_pStock = nullptr;
}
for (i = 0; i < TAB_COUNT; i++) {
if (m_pTab[i] != nullptr) {
delete m_pTab[i];
m_pTab[i] = nullptr;
}
}
if (m_pFound != nullptr) {
delete m_pFound;
m_pFound = nullptr;
}
}
CStack *CBoard::GetStack(loc nStack) {
int i;
switch (nStack) {
case fnd:
return m_pFound;
case stock:
return m_pStock;
case used:
return m_pUsed;
default:
for (i = 0; i < TAB_COUNT; i++)
if (m_pTab[i]->GetID() == nStack)
return m_pTab[i];
}
return nullptr;
}
bool CBoard::IsTabStack(int nStack) {
switch (nStack) {
case fnd:
return false;
case stock:
return false;
case used:
return false;
default:
return true;
}
}
} // namespace Barbershop
} // namespace HodjNPodj
} // 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 HODJNPODJ_BARBERSHOP_BOARD_H
#define HODJNPODJ_BARBERSHOP_BOARD_H
#include "bagel/hodjnpodj/barbershop/paint.h"
#include "bagel/hodjnpodj/barbershop/stack.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
class CBoard {
public: // functions
CBoard(CPaint*);
~CBoard();
CStack *GetStack(loc);
bool IsTabStack(int);
public: // vars
CStack *m_pFound = nullptr;
CStack *m_pTab[TAB_COUNT] = {};
CStack *m_pStock = nullptr;
CStack *m_pUsed = nullptr;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,99 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/barbershop/card.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
OSpr::OSpr() : CSprite() {
m_cCard = nullptr;
}
CCard::CCard() {
m_enSuit = (suit) suit_none;
m_nPip = 0;
m_pPrevCard = nullptr;
m_pNextCard = nullptr;
m_pSprite = nullptr;
m_pStack = nullptr;
m_bIsBack = false;
m_cOrigin = CPoint(0, 0);
}
CCard::CCard(int nValue) {
if (nValue >= SUITS * PIPS) { // Is this a joker card?
m_enSuit = manicurist; // Yes - assign joker suit
m_nPip = MANI_CARD; // and joker pip
} else {
m_enSuit = (suit)(nValue % SUITS); // No - assign usual suit
m_nPip = nValue % PIPS;
}
m_pPrevCard = nullptr;
m_pNextCard = nullptr;
m_pSprite = nullptr;
m_pStack = nullptr;
m_bIsBack = false;
m_cOrigin = CPoint(0, 0);
}
CCard::CCard(suit enSuit, int nPip) {
m_enSuit = enSuit;
m_nPip = nPip;
m_pPrevCard = nullptr;
m_pNextCard = nullptr;
m_pSprite = nullptr;
m_pStack = nullptr;
m_bIsBack = false;
m_cOrigin = CPoint(0, 0);
}
CCard::~CCard() {
}
int CCard::GetValue() const {
if (m_enSuit == manicurist) { // Is Joker suit?
return m_nPip; // return it's special pip
} else {
return m_nPip + (m_enSuit * PIPS);
}
}
CCard &CCard::operator=(const CCard& cCard) {
m_enSuit = cCard.m_enSuit; // Private members
m_nPip = cCard.m_nPip;
m_pPrevCard = cCard.m_pPrevCard; // Public members
m_pNextCard = cCard.m_pNextCard;
m_pStack = cCard.m_pStack;
m_bIsBack = cCard.m_bIsBack;
m_pSprite = cCard.m_pSprite;
m_cOrigin = cCard.m_cOrigin;
return *this;
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,114 @@
/* 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 HODJNPODJ_BARBERSHOP_CARD_H
#define HODJNPODJ_BARBERSHOP_CARD_H
#include "bagel/hodjnpodj/hnplibs/sprite.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define TAB_COUNT 5
#define TAB_STACK 7
#define TABLEAU 35
#define STOCK 27
#define STOCK_DRAW 3
#define SUITS 5
#define PIPS 12
#define ONE_CARD 0
#define TWO_CARD 1
#define THREE_CARD 2
#define FOUR_CARD 3
#define FIVE_CARD 4
#define SIX_CARD 5
#define SEVEN_CARD 6
#define EIGHT_CARD 7
#define NINE_CARD 8
#define TEN_CARD 9
#define CUST_CARD 10
#define BARB_CARD 11
#define MANI_CARD 60
enum suit {suit_none = -1, brush, comb, mirror, razor, sissor, manicurist};
enum loc {loc_none = -1, fnd, tab, stock = 6, used};
class CStack;
class CCard;
class OSpr : public CSprite {
public:
OSpr();
CCard *m_cCard;
};
class CCard {
private: // vars
suit m_enSuit;
int m_nPip;
public: // functions
CCard(suit enSuit, int nPip);
CCard(int);
CCard();
~CCard();
int GetValue() const;
int GetPip() const {
return m_nPip;
}
bool IsFace() const {
return m_nPip >= CUST_CARD;
}
bool IsCustomer() const {
return m_nPip == CUST_CARD;
}
bool IsBarber() const {
return m_nPip == BARB_CARD;
}
bool IsManicurist() {
return m_nPip == MANI_CARD;
}
bool operator==(int nValue) const {
return nValue == GetValue();
}
CCard &operator=(const CCard &);
public: // vars
CCard *m_pPrevCard;
CCard *m_pNextCard;
OSpr *m_pSprite;
CStack *m_pStack;
bool m_bIsBack;
CPoint m_cOrigin;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,91 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/barbershop/deck.h"
#include "bagel/hodjnpodj/barbershop/board.h"
#include "bagel/hodjnpodj/barbershop/stack.h"
#include "bagel/hodjnpodj/hodjnpodj.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
CDeck::CDeck() {
int i;
for (i = 0; i < DECK; i++)
m_cDeck[i] = CCard(i); // Reset deck
//srand((unsigned) time(nullptr)); // seed the random number generator
}
CDeck::~CDeck() {
}
void CDeck::Shuffle() {
int nNewDeck[DECK];
int nCard;
int i;
for (i = 0; i < DECK; i++)
nNewDeck[i] = NOT_USED;
/******************************
* Find an unused encrypt map. *
******************************/
for (i = 0; i < DECK; i++) {
#ifndef REVEAL // change ifndef to ifdef for debugging purposes
do {
nCard = brand() % DECK;
} while (nNewDeck[nCard] == USED); // find unshuffled card
nNewDeck[nCard] = USED; // mark card as shuffled
#else
nCard = i % 2;
if (nCard == 1)
nCard = CUST_CARD;
#endif
m_cDeck[i] = CCard(nCard); // put card into it's new location
}
}
void CDeck::Deal(CBoard *pBoard) {
int nStack, nCard, i;
for (nStack = fnd; nStack <= used; nStack++)
pBoard->GetStack((loc) nStack)->Reset();
for (nStack = tab, i = 1, nCard = 0; nStack < stock; nStack++, i++)
for (; nCard < (i * (TAB_STACK)); nCard++)
pBoard->GetStack((loc) nStack)->Push(&m_cDeck[nCard]);
for (; nCard < (STOCK + TABLEAU); nCard++)
pBoard->GetStack(stock)->Push(&m_cDeck[nCard]);
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,56 @@
/* 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 HODJNPODJ_BARBERSHOP_DECK_H
#define HODJNPODJ_BARBERSHOP_DECK_H
#include "bagel/hodjnpodj/barbershop/card.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define DECK 62
#define STOCK 27
#define NOT_USED -1
#define USED 0
class CBoard;
class CDeck {
public: // func
CDeck(); // constructor
~CDeck(); // destructor
void Shuffle();
void Deal(CBoard*);
public: // vars
CCard m_cDeck[DECK];
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

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/>.
*
*/
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/hodjnpodj/barbershop/main.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
HINSTANCE hDLLInst;
HINSTANCE hExeInst;
extern LPGAMESTRUCT pGameParams;
// global the pointer to the your game's main window
HWND ghParentWnd;
/////////////////////////////////////////////////////////////////////////////
// Public C interface
/*****************************************************************
*
* RunBarb
*
* FUNCTIONAL DESCRIPTION:
*
* This is the API function for the DLL. It is what the calling app
* calls to invoke Barbershop Quintet.
*
* FORMAL PARAMETERS:
*
* hParentWnd, lpGameInfo
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
HWND FAR PASCAL RunBarb(HWND hParentWnd, LPGAMESTRUCT lpGameInfo) {
CMainWindow *pMain;
pGameParams = lpGameInfo;
// invoke your game here by creating a pGame for your main window
// look at the InitInstance for your game for this
ghParentWnd = hParentWnd;
if ((pMain = new CMainWindow) != nullptr) {
pMain->ShowWindow(SW_SHOWNORMAL);
pMain->UpdateWindow();
pMain->SetActiveWindow();
}
// these must be set in this function
hDLLInst = (HINSTANCE)GetWindowWord(pMain->m_hWnd, GWW_HINSTANCE);
hExeInst = (HINSTANCE)GetWindowWord(hParentWnd, GWW_HINSTANCE);
return pMain->m_hWnd; // return the m_hWnd of your main game window
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,38 @@
/* 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 HODJNPODJ_BARBERSHOP_GAMEDLL_H
#define HODJNPODJ_BARBERSHOP_GAMEDLL_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
extern HWND FAR PASCAL RunBarb(HWND hParentWnd, LPGAMESTRUCT lpGameInfo);
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,66 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/barbershop/resource.h"
#include "bagel/hodjnpodj/barbershop/usercfg.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
void MyFocusRect(CDC *pDC, CRect rect, int nDrawMode) {
CBrush *pMyBrush = nullptr; // New Brush
CBrush *pOldBrush = nullptr; // Pointer to old brush
CPen *pMyPen = nullptr; // New Pen
CPen *pOldPen = nullptr; // Pointer to old pen
CPalette *pPalOld = nullptr; // Pointer to old palette
int OldDrawMode; // Holder for old draw mode
pMyBrush = new CBrush(); // Construct new brush
pMyPen = new CPen(); // Construct new pen
LOGBRUSH lb; // log brush type
lb.lbStyle = BS_HOLLOW; // Don't fill in area
pMyBrush->CreateBrushIndirect(&lb); // Create a new brush
pMyPen->CreatePen(PS_INSIDEFRAME, HILITE_BORDER, RGBCOLOR_DARKRED); // Create a new pen
pPalOld = (*pDC).SelectPalette(pGamePalette, false); // Select in game palette
(*pDC).RealizePalette(); // Use it
pOldPen = pDC->SelectObject(pMyPen); // Select the new pen & save old
pOldBrush = pDC->SelectObject(pMyBrush); // Select the new brush & save old
OldDrawMode = pDC->SetROP2(nDrawMode); // Set pen mode, saving old state
pDC->Rectangle(rect); // Draw the Rectangle to the DC
pDC->SelectObject(pOldPen); // Select the old pen
pDC->SelectObject(pOldBrush); // Select the old brush
pDC->SetROP2(OldDrawMode); // Set pen mode back to old state
(*pDC).SelectPalette(pPalOld, false); // Select back the old palette
pMyBrush->DeleteObject();
delete pMyBrush;
pMyPen->DeleteObject();
delete pMyPen;
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,315 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/barbershop/logic.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
/*****************************************************************
*
* Logic
*
* FUNCTIONAL DESCRIPTION:
*
* Destructor
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
CLogic::CLogic() {
}
/*****************************************************************
*
* ~Logic
*
* FUNCTIONAL DESCRIPTION:
*
* Destructor
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
CLogic::~CLogic() {
}
/*****************************************************************
*
* IsMoveOk
*
* FUNCTIONAL DESCRIPTION:
*
* Destructor
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
bool CLogic::IsMoveOk(CCard *pCard, CStack *pStack) {
CCard *pTopCard;
switch (pStack->GetID()) {
case fnd: // foundation rules
if (pCard->IsFace() == true)
return true;
if (pStack->IsEmpty() == true)
return false;
pTopCard = pStack->Top();
if (pTopCard->IsManicurist() == true)
return true;
if (
pTopCard->IsCustomer() == true &&
pCard->GetPip() == ONE_CARD
)
return true;
if (
pTopCard->IsBarber() == true &&
pCard->GetPip() == TEN_CARD
)
return true;
if (pTopCard->GetPip() == ONE_CARD) {
if (pCard->GetPip() == TWO_CARD) {
return true;
} else {
return false;
}
}
if (pTopCard->GetPip() == TEN_CARD) {
if (pCard->GetPip() == NINE_CARD) {
return true;
} else {
return false;
}
}
if (
(
pTopCard->GetPip() == (pCard->GetPip() + 1) ||
pTopCard->GetPip() == (pCard->GetPip() - 1)
) &&
pTopCard->IsFace() == false
)
return true;
return false;
case stock:
return false;
case used:
return false;
default: // tab
if (pStack->IsEmpty() == true) { // empty space on tab?
if ( // yes - source card from stack with other face cards?
pCard->m_pStack->GetID() >= tab &&
pCard->m_pStack->GetID() < stock &&
pCard->m_pPrevCard != nullptr &&
pCard->m_pPrevCard->m_bIsBack == true
)
return true; // this is a valid move
if ( // yes - source card from stock?
pCard->m_pStack->GetID() == used
)
return true; // this is a valid move
return false;
}
if (
pStack->IsEmpty() == true &&
pCard->m_pStack->GetID() >= tab &&
pCard->m_pStack->GetID() < stock &&
pCard->m_pPrevCard != nullptr &&
pCard->m_pPrevCard->m_bIsBack == true
) // when there's an empty space on the tab
return true;
pTopCard = pStack->Top();
if (pCard == pTopCard) // card back on it's own stack?
return false; // yes, illegal
if (pTopCard->m_bIsBack == true)
return false;
if (
pTopCard->IsManicurist() == true &&
pCard->IsManicurist() == true
)
return true;
if (pTopCard->GetPip() == pCard->GetPip()) {
if (pCard->m_pStack->GetID() == used) // Card from used stack?
return true; // yes - acceptable move
if (pCard->m_pPrevCard == nullptr) // anything under cur card?
return true; // no
if (pCard->m_pPrevCard->m_bIsBack == true) // card under cur card a card back?
return true; // yes
return false;
}
return false;
}
}
bool CLogic::IsGameOver(CBoard *pBoard) {
CStack *pFnd;
CCard *pCard;
int i, j;
pFnd = pBoard->GetStack((loc) fnd);
if (pFnd->Size() == DECK) // All cards on foundation?
return true; // Yes
/******************************************************
* Check all combinations of tableau to tableau moves. *
******************************************************/
for (i = tab; i < stock; i++) {
if ((pCard = pBoard->GetStack((loc) i)->Top()) == nullptr)
continue;
if (pCard->m_bIsBack == true)
return false;
for (j = tab; j < stock; j++) {
if (pCard->m_pStack == pBoard->GetStack((loc) j))
continue;
if (IsMoveOk(pCard, pBoard->GetStack((loc) j)) == true)
return false;
} // end for
} // end for
//return false; // used for debugging purposes
/*********************************************************
* Check all combinations of tableau to foundation moves. *
*********************************************************/
for (i = tab; i < stock; i++) {
if ((pCard = pBoard->GetStack((loc) i)->Top()) == nullptr)
continue;
if (IsMoveOk(pCard, pFnd) == true)
return false;
} // end for
/************************************
* Check all combinations of *
* - used stack to tableau moves. *
* - used stack to foundation. *
* - stock to tableau moves. *
* - stock to foundation. *
************************************/
pCard = pBoard->GetStack((loc) stock)->Top();
while (pCard != nullptr) {
for (j = 0; j < STOCK_DRAW; j++) {
if (pCard->m_pStack->Bottom() == pCard) // Out of cards on the Stock stack?
break;
if (pCard->m_pStack->Top() == pCard) // if top, skip a count
j++;
pCard = pCard->m_pPrevCard;
} // end for
for (j = fnd; j < stock; j++) {
if (IsMoveOk(pCard, pBoard->GetStack((loc) j)) == true)
return false;
} // end for
if (pCard->m_pStack->Bottom() == pCard) // Out of cards on the Stock stack?
break;
} // end while
pCard = pBoard->GetStack((loc) used)->Bottom();
while (pCard != nullptr) {
for (j = 0; j < STOCK_DRAW; j++) {
if (pCard->m_pStack->Top() == pCard) // Out of cards on the Stock stack?
break;
if (pCard->m_pStack->Bottom() == pCard) // if bottom, skip a count
j++;
pCard = pCard->m_pNextCard;
} // end for
for (j = fnd; j < stock; j++) {
if (IsMoveOk(pCard, pBoard->GetStack((loc) j)) == true)
return false;
} // end for
if (pCard->m_pStack->Top() == pCard) // Out of cards on the Stock stack?
break;
} // end while
return true; // Game over, no other possible moves
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,46 @@
/* 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 HODJNPODJ_BARBERSHOP_LOGIC_H
#define HODJNPODJ_BARBERSHOP_LOGIC_H
#include "bagel/hodjnpodj/barbershop/stack.h"
#include "bagel/hodjnpodj/barbershop/board.h"
#include "bagel/hodjnpodj/barbershop/card.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
class CLogic {
public:
CLogic();
~CLogic();
bool IsMoveOk(CCard*, CStack*);
bool IsGameOver(CBoard *pBoard);
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,953 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/dibdoc.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/hnplibs/mainmenu.h"
#include "bagel/hodjnpodj/hnplibs/cmessbox.h"
#include "bagel/boflib/misc.h"
#include "bagel/hodjnpodj/hnplibs/rules.h"
#include "bagel/boflib/error.h"
#include "bagel/hodjnpodj/barbershop/init.h"
#include "bagel/hodjnpodj/barbershop/main.h"
#include "bagel/hodjnpodj/barbershop/undo.h"
#include "bagel/hodjnpodj/barbershop/usercfg.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
//
// This mini-game's main screen bitmap
//
#define MINI_GAME_MAP ".\\ART\\barb.BMP"
//
// This mini-game's sound file
//
#define MIDI_SOUND ".\\SOUND\\barber.mid"
#define RULES_TXT "barb.txt"
#define RULES_WAV ".\\sound\\rlbq.wav"
//
// Win/Lose conditions
//
#define WIN 1
#define LOSE 0
//
// Button ID constants
//
#define IDC_MENU 100
#define TIMER_ID 10
// Local Prototypes
//
void CALLBACK GetGameParams(CWnd *);
//
// Globals
//
CPalette *pGamePalette;
LPGAMESTRUCT pGameParams;
int g_nCardBack;
extern HWND ghParentWnd;
CMainWindow::CMainWindow() {
CString WndClass;
CRect tmpRect;
CDC *pDC = nullptr;
CDibDoc *pDibDoc;
ERROR_CODE errCode;
bool bSuccess;
// assume no error
errCode = ERR_NONE;
// Initialize members
//
m_pScrollSprite = nullptr;
m_pGamePalette = nullptr;
m_bPause = false;
m_bGameActive = false;
m_bInMenu = false;
m_bMIDIPlaying = false;
m_pBarb = nullptr;
m_pMIDISound = nullptr;
// Initialize score to LOSE condition in case the user bails out
//
pGameParams->lScore = LOSE;
// Set the coordinates for the "Start New Game" button
//
m_rNewGameButton.SetRect(15, 4, 233, 20);
// Define a special window class which traps double-clicks, is byte aligned
// to maximize BITBLT performance, and creates "owned" DCs rather than sharing
// the five system defined DCs which are not guaranteed to be available;
// this adds a bit to our app size but avoids hangs/freezes/lockups.
WndClass = AfxRegisterWndClass(CS_DBLCLKS | CS_BYTEALIGNWINDOW | CS_OWNDC, nullptr, nullptr, nullptr);
// can't play this game if the background art is not available
//
if (FileExists(MINI_GAME_MAP)) {
// Acquire the shared palette for our game from the splash screen art
//
if ((pDibDoc = new CDibDoc()) != nullptr) {
if (pDibDoc->OpenDocument(MINI_GAME_MAP) != false)
pGamePalette = m_pGamePalette = pDibDoc->DetachPalette();
else
errCode = ERR_UNKNOWN;
delete pDibDoc;
} else {
errCode = ERR_MEMORY;
}
} else {
errCode = ERR_FFIND;
}
// Center our window on the screen
//
tmpRect.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
if ((pDC = GetDC()) != nullptr) {
tmpRect.left = (pDC->GetDeviceCaps(HORZRES) - GAME_WIDTH) >> 1;
tmpRect.top = (pDC->GetDeviceCaps(VERTRES) - GAME_HEIGHT) >> 1;
tmpRect.right = tmpRect.left + GAME_WIDTH;
tmpRect.bottom = tmpRect.top + GAME_HEIGHT;
ReleaseDC(pDC);
} else {
errCode = ERR_UNKNOWN;
}
// Create the window as a POPUP so no boarders, title, or menu are present;
// this is because the game's background art will fill the entire 640x480 area.
//
Create(WndClass, "Boffo Games -- Barbershop Quintet", WS_POPUP, tmpRect, nullptr, 0);
BeginWaitCursor();
ShowWindow(SW_SHOWNORMAL);
PaintScreen();
EndWaitCursor();
// only continue if there was no error
//
if (errCode == ERR_NONE) {
if ((pDC = GetDC()) != nullptr) {
//
// build our main menu button
//
if ((m_pScrollSprite = new CSprite) != nullptr) {
m_pScrollSprite->SharePalette(m_pGamePalette);
bSuccess = m_pScrollSprite->LoadSprite(pDC, ".\\ART\\SCROLBTN.BMP");
assert(bSuccess);
if (bSuccess) {
m_pScrollSprite->SetMasked(true);
m_pScrollSprite->SetMobile(true);
} else {
errCode = ERR_UNKNOWN;
}
} else {
errCode = ERR_MEMORY;
}
// only continue if there was no error
//
if (errCode == ERR_NONE) {
// seed the random number generator
//srand((unsigned)time(nullptr));
}
ReleaseDC(pDC);
}
}
if (errCode == ERR_NONE) {
//
// Initialize midi music
//
if ((m_pMIDISound = new CSound((CWnd *) this, MIDI_SOUND, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END)) == nullptr) {
errCode = ERR_MEMORY;
}
}
if (errCode == ERR_NONE) {
//
// Initialize wav sound
//
if ((m_pWavSound = new CSound) == nullptr) {
errCode = ERR_MEMORY;
}
}
if (errCode == ERR_NONE) {
//
// Initialize Barbershop Quintet!
//
if ((m_pBarb = new CBarber(pDC, m_pWavSound)) == nullptr) {
errCode = ERR_MEMORY;
} else {
g_nCardBack = m_pBarb->m_cPnt->m_nCardBack;
} // end if
}
if (errCode == ERR_NONE) {
//
// Initialize animations
//
if ((m_pAnim = new CAnimate(m_pWavSound)) == nullptr) {
errCode = ERR_MEMORY;
}
}
if (errCode == ERR_NONE) {
// Start the game theme song
//
if (pGameParams->bMusicEnabled) {
m_bMIDIPlaying = true;
m_pMIDISound->midiLoopPlaySegment(2000L, 33560L, 00L, FMT_MILLISEC);
}
// Automatically bring up the main menu if in stand alone mode
//
if (pGameParams->bPlayingMetagame != false) {
PostMessage(WM_COMMAND, IDC_OPTIONS_NEWGAME, BN_CLICKED);
} else {
PostMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
}
}
HandleError(errCode);
}
void CMainWindow::HandleError(ERROR_CODE errCode) {
//
// Exit this application on fatal errors
//
if (errCode != ERR_NONE) {
// pause the current game (if any)
GamePause();
// Display Error Message to the user
MessageBox(errList[errCode], "Fatal Error!", MB_OK | MB_ICONSTOP);
// Force this application to terminate
PostMessage(WM_CLOSE, 0, 0);
// Don't allow a repaint (remove all WM_PAINT messages)
ValidateRect(nullptr);
}
}
void CMainWindow::OnPaint() {
PAINTSTRUCT lpPaint;
Invalidate(false);
BeginPaint(&lpPaint);
PaintScreen();
EndPaint(&lpPaint);
}
void CMainWindow::PaintScreen() {
//CSprite *pSprite;
CDibDoc myDoc;
CRect rcDest;
CRect rcDIB;
HDIB hDIB;
CDC *pDC;
//
// Paint the background art and upadate any sprites
// called by OnPaint
//
if (FileExists(MINI_GAME_MAP)) {
myDoc.OpenDocument(MINI_GAME_MAP);
hDIB = myDoc.GetHDIB();
pDC = GetDC();
assert(pDC != nullptr);
if (pDC != nullptr) {
if (hDIB && (m_pGamePalette != nullptr)) {
GetClientRect(rcDest);
rcDIB.top = rcDIB.left = 0;
rcDIB.right = (int) DIBWidth(hDIB);
rcDIB.bottom = (int) DIBHeight(hDIB);
PaintDIB(pDC->m_hDC, &rcDest, hDIB, &rcDIB, m_pGamePalette);
}
// repaint the command scroll
//
if (!m_bInMenu && (m_pScrollSprite != nullptr)) {
m_pScrollSprite->PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
}
if (m_pBarb != nullptr)
m_pBarb->Refresh(pDC); // repaint the board of cards
ReleaseDC(pDC);
}
}
}
bool CMainWindow::OnCommand(WPARAM wParam, LPARAM lParam) {
CDC *pDC;
bool bSuccess;
if (HIWORD(lParam) == BN_CLICKED) {
switch (wParam) {
//
// must bring up our menu of controls
//
case IDC_MENU: {
GamePause();
// don't display the command scroll when in the menu
m_bInMenu = true;
// hide the command scroll
//
pDC = GetDC();
bSuccess = m_pScrollSprite->EraseSprite(pDC);
// Create the commands menu
//
CMainMenu COptionsWind(
(CWnd *)this,
m_pGamePalette,
//NO_OPTIONS |
(m_bGameActive ? 0 : NO_RETURN) |
(pGameParams->bPlayingMetagame ? NO_OPTIONS : 0) |
(pGameParams->bPlayingMetagame ? NO_NEWGAME : 0),
GetGameParams,
RULES_TXT,
pGameParams->bSoundEffectsEnabled ? RULES_WAV : nullptr,
pGameParams
);
CSound::waitWaveSounds();
// Get users choice from command menu
//
switch (COptionsWind.DoModal()) {
// User has chosen to play a new game
//
case IDC_OPTIONS_NEWGAME:
if (m_pBarb->IsNewBack(g_nCardBack) == true) { // need to card back?
m_pBarb->ChangeBack(pDC, g_nCardBack); // yes - change it
} // end if
PlayGame();
break;
// User has chosen to quit this mini-game
//
case IDC_OPTIONS_QUIT:
pGameParams->lScore = LOSE; // make sure the score is zero if they quit
PostMessage(WM_CLOSE, 0, 0);
break;
default:
if (m_pBarb->IsNewBack(g_nCardBack) == true) { // need to card back?
m_pBarb->ChangeBack(pDC, g_nCardBack); // yes - change it
Invalidate(true); // set up for a redraw window
} // end if
break;
} // end switch
if (!pGameParams->bMusicEnabled && m_bMIDIPlaying) {
m_pMIDISound->stop();
m_bMIDIPlaying = false;
} else if (pGameParams->bMusicEnabled && !m_bMIDIPlaying) {
m_pMIDISound->midiLoopPlaySegment(2470, 32160, 0, FMT_MILLISEC);
m_bMIDIPlaying = true;
}
// show the command scroll
//
bSuccess = m_pScrollSprite->PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
assert(bSuccess);
ReleaseDC(pDC);
// ok to display the command scroll now
//
m_bInMenu = false;
GameResume();
return true;
} // end case
case IDC_OPTIONS_NEWGAME:
PlayGame();
break;
} // end switch
} // end if
return false;
}
void CMainWindow::GamePause() {
m_bPause = true;
}
void CMainWindow::GameResume() {
m_bPause = false;
}
void CMainWindow::PlayGame() {
CDC *pDC;
ERROR_CODE errCode;
// assume no error
errCode = ERR_NONE;
// load the .INI settings
//
LoadIniSettings();
// reset all game parameters
//
GameReset();
if (errCode == ERR_NONE) {
if ((pDC = GetDC()) != nullptr) {
//
// Start game
//
//CSprite::FlushSprites();
CSprite::FlushSpriteChain(); // Delete cards from memory
Invalidate(true);
UpdateWindow();
/*
if ( pGameParams->bMusicEnabled != false ) {
m_pMIDISound->midiLoopPlaySegment(2000L, 33560L, 00L, FMT_MILLISEC);
}
*/
m_pBarb->NewGame(pDC);
m_bGameActive = true;
ReleaseDC(pDC);
} else {
errCode = ERR_MEMORY;
} // end if
} // end if
HandleError(errCode);
}
void CMainWindow::LoadIniSettings() {
}
void CMainWindow::SaveIniSettings() {
}
void CMainWindow::GameReset() {
//sndPlaySound(nullptr, SND_SYNC); // stop all sounds
}
void CMainWindow::OnTimer(uintptr nEvent) {
//CDC *pDC;
// continue as long as there is a currently active non-paused game
//
//if (m_bGameActive && !m_bPause) {
// nEvent = 0x00; // bull shit code rids warnings
//}
}
void CMainWindow::OnMouseMove(unsigned int nFlags, CPoint point) {
CDC *pDC;
SetCursor(LoadCursor(nullptr, IDC_ARROW));
if (m_pBarb->m_pCrd != nullptr) {
pDC = GetDC();
m_pBarb->OnMouseMove(pDC, point);
ReleaseDC(pDC);
}
//nFlags = 0x00;
}
void CMainWindow::OnRButtonDown(unsigned int nFlags, CPoint point) {
CPoint UndoPoint(UNDO_LEF + (UNDO_RIG - UNDO_LEF) / 2, UNDO_TOP + (UNDO_BOT - UNDO_TOP) / 2);
if (m_pBarb->m_pCrd != nullptr) // r we currently moving a card?
return; // Yes - just quit.
if (m_pBarb->m_bIsGameOver == false) {
m_pBarb->OnLButtonDown(
(CWnd*) this,
m_pGamePalette,
UndoPoint
);
}
}
void CMainWindow::OnLButtonDown(unsigned int nFlags, CPoint point) {
CDC *pDC;
char buf[32];
CRect tmpRect;
if (m_pBarb->m_pCrd != nullptr) // r we currently moving a card?
return; // Yes - just quit.
if (m_pScrollSprite != nullptr)
tmpRect = m_pScrollSprite->GetRect();
pDC = GetDC();
// User clicked on the Menu button
//
if (tmpRect.PtInRect(point)) {
// bring up the menu
PostMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
// User clicked on the Title - NewGame button
//
} else if (m_rNewGameButton.PtInRect(point)) {
// start a new game
if (pGameParams->bPlayingMetagame == false)
PlayGame();
} else if (m_pAnim->Clown(pDC, point) == true) {
/************************************
* user clicked animation. *
* animation handled in it's call. *
************************************/
FlushInputEvents();
} else if (m_pAnim->UFO(pDC, point) == true) {
/************************************
* user clicked animation. *
* animation handled in it's call. *
************************************/
FlushInputEvents();
} else if (m_pAnim->Brat(point) == true) {
/************************************
* user clicked animation. *
* animation handled in it's call. *
************************************/
FlushInputEvents();
} else if (m_pAnim->Lollipop(point) == true) {
/************************************
* user clicked animation. *
* animation handled in it's call. *
************************************/
FlushInputEvents();
} else if (m_pAnim->Haircut(point) == true) {
/************************************
* user clicked animation. *
* animation handled in it's call. *
************************************/
FlushInputEvents();
} else if (m_pBarb->m_bIsGameOver == false) {
m_pBarb->OnLButtonDown(
(CWnd*) this,
m_pGamePalette,
point
);
// is this needed ?
CFrameWnd::OnLButtonDown(nFlags, point);
if (m_pBarb->m_bIsGameOver == true) {
if (pGameParams->bPlayingMetagame) {
Common::sprintf_s(buf, "Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
PostMessage(WM_CLOSE, 0, 0);
} else if (m_pBarb->m_bIsWin) {
Common::sprintf_s(buf, "You win! Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
} else {
Common::sprintf_s(buf, "Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
} // end if
} // end if
} // end if
ReleaseDC(pDC);
}
void CMainWindow::OnLButtonDblClk(unsigned int nFlags, CPoint point) {
char buf[32];
CRect tmpRect;
if (m_pScrollSprite != nullptr)
tmpRect = m_pScrollSprite->GetRect();
// User clicked on the Menu button
//
if (tmpRect.PtInRect(point)) {
// bring up the menu
PostMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
// User clicked on the Title - NewGame button
//
} else if (m_rNewGameButton.PtInRect(point)) {
// start a new game
if (pGameParams->bPlayingMetagame == false)
PlayGame();
} else if (m_pBarb->m_bIsGameOver == false) {
m_pBarb->OnLButtonDblClk(
(CWnd*) this,
m_pGamePalette,
point
);
if (m_pBarb->m_bIsGameOver == true) {
if (pGameParams->bPlayingMetagame) {
Common::sprintf_s(buf, "Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game Over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
PostMessage(WM_CLOSE, 0, 0);
} else if (m_pBarb->m_bIsWin) {
Common::sprintf_s(buf, "You win! Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game Over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
} else {
Common::sprintf_s(buf, "Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game Over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
} // end if
} // end if
} // end if
}
void CMainWindow::OnLButtonUp(unsigned int nFlags, CPoint point) {
char buf[32];
if (m_pBarb->m_bIsGameOver == false) {
m_pBarb->OnLButtonUp((CWnd*) this);
if (m_pBarb->m_bIsGameOver == true) {
if (pGameParams->bPlayingMetagame) {
Common::sprintf_s(buf, "Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game Over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
PostMessage(WM_CLOSE, 0, 0);
} else if (m_pBarb->m_bIsWin) {
Common::sprintf_s(buf, "You win! Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game Over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
} else {
Common::sprintf_s(buf, "Score: %d", m_pBarb->Score());
CMessageBox cGameOver(
(CWnd*) this,
m_pGamePalette,
"Game Over.",
buf
);
pGameParams->lScore = m_pBarb->Score();
} // end if
} // end if
} // end if
}
void CMainWindow::DeleteSprite(CSprite *pSprite) {
CDC *pDC;
// can't delete a null pointer
assert(pSprite != nullptr);
if ((pDC = GetDC()) != nullptr) {
pSprite->EraseSprite(pDC); // erase it from screen
ReleaseDC(pDC);
}
pSprite->UnlinkSprite(); // unlink it
delete pSprite; // delete it
}
void CMainWindow::OnSysChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
// terminate app on ALT_Q
//
if ((nChar == 'q') && (nFlags & 0x2000)) {
pGameParams->lScore = LOSE; // make sure the score is zero if they quit
PostMessage(WM_CLOSE, 0, 0);
} else {
// default action
CFrameWnd ::OnSysChar(nChar, nRepCnt, nFlags);
}
}
void CMainWindow::OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
switch (nChar) {
// User has hit ALT_F4 so close down this App
//
case VK_F4:
pGameParams->lScore = LOSE; // make sure the score is zero if they quit
PostMessage(WM_CLOSE, 0, 0);
break;
default:
CFrameWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
break;
}
}
void CMainWindow::OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
// Handle keyboard input
//
switch (nChar) {
//
// Bring up the Rules
//
case VK_F1: {
if (m_pBarb->m_pCrd != nullptr) { // user holding a card?
break; // yeap, can't allow this
}
GamePause();
CSound::waitWaveSounds();
CRules RulesDlg(this, RULES_TXT, m_pGamePalette, pGameParams->bSoundEffectsEnabled ? RULES_WAV : nullptr);
RulesDlg.DoModal();
GameResume();
}
break;
//
// Bring up the options menu
//
case VK_F2:
if (m_pBarb->m_pCrd != nullptr) { // user holding a card?
break; // yeap, can't allow this
}
SendMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
break;
default:
CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
break;
}
}
void CMainWindow::FlushInputEvents() {
MSG msg;
while (true) { // find and remove all keyboard events
if (!PeekMessage(&msg, nullptr, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
break;
} // end while
while (true) { // find and remove all mouse events
if (!PeekMessage(&msg, nullptr, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
break;
} // end while
}
void CMainWindow::OnActivate(unsigned int nState, CWnd *pWndOther, bool bMinimized) {
if (!bMinimized) {
switch (nState) {
case WA_ACTIVE:
case WA_CLICKACTIVE:
InvalidateRect(nullptr, false);
break;
default:
break;
}
}
}
LRESULT CMainWindow::OnMCINotify(WPARAM wParam, LPARAM lParam) {
//CSound *pSound;
CSound::OnMCIStopped(wParam, lParam);
// if (pSound != nullptr)
// OnSoundNotify(pSound);
return 0;
}
LRESULT CMainWindow::OnMMIONotify(WPARAM wParam, LPARAM lParam) {
//CSound *pSound;
CSound::OnMMIOStopped(wParam, lParam);
//if (pSound != nullptr)
// OnSoundNotify(pSound);
return 0;
}
void CMainWindow::OnClose() {
CDC *pDC = GetDC();
CRect rctFillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
CBrush Brush(RGB(0, 0, 0));
pDC->FillRect(&rctFillRect, &Brush);
ReleaseDC(pDC);
// perform cleanup
//
GameReset();
if (m_pAnim != nullptr) {
delete m_pAnim;
m_pAnim = nullptr;
}
if (m_pMIDISound != nullptr || m_pWavSound != nullptr) {
CSound::clearSounds(); // turn all sounds totally off and delete the objects
m_pMIDISound = nullptr;
m_pWavSound = nullptr;
}
if (m_pBarb != nullptr) {
delete m_pBarb;
m_pBarb = nullptr;
}
//
// de-allocate any controls that we used
//
assert(m_pScrollSprite != nullptr);
if (m_pScrollSprite != nullptr)
delete m_pScrollSprite;
//
// need to de-allocate the game palette
//
assert(m_pGamePalette != nullptr);
if (m_pGamePalette != nullptr) {
//m_pGamePalette->DeleteObject();
delete m_pGamePalette;
}
CFrameWnd::OnClose();
MFC::PostMessage(ghParentWnd, WM_PARENTNOTIFY, WM_DESTROY, (LPARAM)pGameParams);
}
//
// CMainWindow message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_PAINT()
ON_WM_CLOSE()
ON_WM_TIMER()
ON_WM_MOUSEMOVE()
ON_WM_SYSCHAR()
ON_WM_KEYDOWN()
ON_WM_SYSKEYDOWN()
ON_WM_RBUTTONDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONUP()
ON_MESSAGE(MM_MCINOTIFY, CMainWindow::OnMCINotify)
ON_MESSAGE(MM_WOM_DONE, CMainWindow::OnMMIONotify)
END_MESSAGE_MAP()
void CALLBACK GetGameParams(CWnd *pParentWnd) {
//
// Our user preference dialog box is self contained in this object
//
CUserCfgDlg dlgUserCfg(pParentWnd, pGamePalette, IDD_USERCFG);
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,91 @@
/* 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 HODJNPODJ_BARBERSHOP_MAIN_H
#define HODJNPODJ_BARBERSHOP_MAIN_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/hodjnpodj/hnplibs/sprite.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/boflib/error.h"
#include "bagel/boflib/sound.h"
#include "bagel/hodjnpodj/barbershop/barb.h"
#include "bagel/hodjnpodj/barbershop/animate.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
class CMainWindow : public CFrameWnd {
private:
CBarber *m_pBarb;
CSound *m_pMIDISound;
CSound *m_pWavSound;
CAnimate *m_pAnim;
bool m_bMIDIPlaying;
public:
CMainWindow();
void PlayGame();
void PaintScreen();
void LoadIniSettings();
void SaveIniSettings();
void FlushInputEvents();
LRESULT OnMCINotify(WPARAM, LPARAM);
LRESULT OnMMIONotify(WPARAM, LPARAM);
protected:
void GameReset();
void GamePause();
void GameResume();
virtual bool OnCommand(WPARAM wParam, LPARAM lParam) override;
void HandleError(ERROR_CODE);
void DeleteSprite(CSprite *);
void OnPaint();
void OnTimer(uintptr);
void OnMouseMove(unsigned int, CPoint);
void OnLButtonDown(unsigned int, CPoint);
void OnLButtonDblClk(unsigned int, CPoint);
void OnRButtonDown(unsigned int, CPoint);
void OnSysChar(unsigned int, unsigned int, unsigned int);
void OnSysKeyDown(unsigned int, unsigned int, unsigned int);
void OnKeyDown(unsigned int, unsigned int, unsigned int);
void OnActivate(unsigned int, CWnd *, bool) override;
void OnClose();
void OnLButtonUp(unsigned int, CPoint);
DECLARE_MESSAGE_MAP()
CRect m_rNewGameButton;
CPalette *m_pGamePalette;
CSprite *m_pScrollSprite;
bool m_bGameActive;
bool m_bPause;
bool m_bInMenu;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,523 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/barbershop/paint.h"
#include "bagel/hodjnpodj/barbershop/barb.h"
#include "bagel/hodjnpodj/hnplibs/bitmaps.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
static const char *DECKS[] = { // bitmap loading
"art\\deck0.bmp",
"art\\deck1.bmp",
"art\\deck2.bmp",
"art\\deck3.bmp",
"art\\deck4.bmp",
"art\\deck5.bmp",
"art\\deck6.bmp",
"art\\deck7.bmp"
};
/*****************************************************************
*
* CPaint
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
CPaint::CPaint(CDC *pDC) {
CBitmap *pBmpCardSet = nullptr;
CBitmap *pCard = nullptr;
bool bSuccess;
int i, j;
for (i = 0; i < CARDS_PER_COL; i++) { // Initialize master alphabet list
pBmpCardSet = FetchBitmap(pDC, (CPalette**) nullptr, DECKS[i]);
ASSERT(pBmpCardSet);
for (j = 0; j < CARDS_PER_ROW; j ++) {
pCard = ExtractBitmap( // fetch the proper card
pDC,
pBmpCardSet,
pGamePalette,
j * BITMAP_WTH,
0,
BITMAP_WTH,
BITMAP_HEI
);
ASSERT(pCard);
m_cCardSet[(i * CARDS_PER_ROW) + j] = new OSpr(); // Initize the individual letter of the alphabet list
bSuccess = (*m_cCardSet[(i * CARDS_PER_ROW) + j]).LoadSprite(pCard, pGamePalette);
ASSERT(bSuccess);
(*m_cCardSet[(i * CARDS_PER_ROW) + j]).SetHotspot(CARD_HOT_X, CARD_HOT_Y);
(*m_cCardSet[(i * CARDS_PER_ROW) + j]).SetMobile(true);
(*m_cCardSet[(i * CARDS_PER_ROW) + j]).SetMasked(true);
} // end for
delete pBmpCardSet;
pBmpCardSet = nullptr;
} // end for
m_nCardBack = CARD_BACK1;
m_nUsedInd = 0; // Used in Stack() proc; for indenting cards placed on used stack
m_cFound.SetRect(
FND_LEF,
FND_TOP,
FND_RIG,
FND_BOT
);
for (i = 0; i < TAB_COUNT; i++)
m_cTab[i].SetRect(
TAB_LEF + (TAB_OFFSET * i),
TAB_TOP,
TAB_RIG + (TAB_OFFSET * i),
TAB_BOT
);
m_cStock.SetRect(
STOC_LEF,
STOC_TOP,
STOC_RIG,
STOC_BOT
);
m_cUsed.SetRect(
STOC_LEF + USED_OFFSET,
STOC_TOP,
STOC_RIG + USED_OFFSET,
STOC_BOT
);
}
/*****************************************************************
*
* ~CPaint
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
CPaint::~CPaint() {
int i;
CSprite::FlushSpriteChain();
for (i = 0; i < CARD_SET; i++)
delete m_cCardSet[i]; // each letter in the alpha
}
/*****************************************************************
*
* Board
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CPaint::Board(CDC *pDC, CBoard *pBoard) {
int i, j;
CCard *pCard[TAB_COUNT];
/************************************************************
* Goes thru each stack on the tableau, dealing cards one at *
* a time rotating to next stack, in turn. *
************************************************************/
for (i = 0; i < TAB_COUNT; i++)
pCard[i] = pBoard->GetStack((loc)(tab + (loc) i))->Bottom();
for (i = 0; i < TABLEAU; i++) {
j = i % TAB_COUNT;
m_pSprite = new OSpr();
if (pCard[j] == pCard[j]->m_pStack->Top()) {
m_cCardSet[pCard[j]->GetValue()]->DuplicateSprite(pDC, (CSprite*) m_pSprite);
m_pSprite->m_cCard = pCard[j];
(*m_pSprite).LinkSprite();
pCard[j]->m_bIsBack = false;
} else {
m_cCardSet[m_nCardBack]->DuplicateSprite(pDC, (CSprite*) m_pSprite);
m_pSprite->m_cCard = pCard[j];
(*m_pSprite).LinkSprite();
pCard[j]->m_bIsBack = true;
} // end if
pCard[j]->m_pSprite = m_pSprite;
Stack(pDC, pCard[j], (int) i / TAB_COUNT);
pCard[j] = pCard[j]->m_pNextCard; // Advance to next card
} // end for
/************************************************************
* used any random pCard index, didn't matter, so 0 is used. *
************************************************************/
pCard[0] = pBoard->GetStack(stock)->Bottom(); // Get first card in stack
i = 0;
while (pCard[0] != nullptr) {
m_pSprite = new OSpr(); // set up visual sprite
m_cCardSet[m_nCardBack]->DuplicateSprite(pDC, (CSprite*) m_pSprite);
(*m_pSprite).LinkSprite();
m_pSprite->m_cCard = pCard[0]; // update internal card struct
pCard[0]->m_pSprite = m_pSprite;
pCard[0]->m_bIsBack = true;
Stack(pDC, pCard[0], i); // paint it on screen
pCard[0] = pCard[0]->m_pNextCard; // Advance to next card
i++;
} // end while
}
void CPaint::Refresh(CDC *pDC, CBoard *pBoard) {
int i;
int nCardPos; // card pos in stack
CStack *pStack;
CCard *pCard;
CPoint cPos;
m_pSprite = (OSpr*) OSpr::GetSpriteChain();
if (m_pSprite == nullptr) // any sprites to refresh?
return; // no
OSpr::ClearBackgrounds();
pStack = pBoard->GetStack(fnd); // refresh foundation
pCard = pStack->Bottom();
nCardPos = 0;
while (pCard != nullptr) {
if (pCard->m_pSprite != nullptr) {
pCard->m_pSprite->RefreshSprite(pDC);
}
pCard = pCard->m_pNextCard;
nCardPos++;
}
for (i = tab; i < stock; i++) { // refresh tableau
pStack = pBoard->GetStack((loc) i);
pCard = pStack->Bottom();
nCardPos = 0;
while (pCard != nullptr) {
if (pCard->m_pSprite != nullptr) {
pCard->m_pSprite->RefreshSprite(pDC);
}
pCard = pCard->m_pNextCard;
nCardPos++;
} // end while
} // end for
pStack = pBoard->GetStack(stock); // refresh stock top card only
pCard = pStack->Bottom();
nCardPos = 0;
while (pCard != nullptr) {
if (pCard->m_pSprite != nullptr) {
pCard->m_pSprite->RefreshSprite(pDC);
}
pCard = pCard->m_pNextCard;
nCardPos++;
}
pStack = pBoard->GetStack(used); // refresh used stack
pCard = pStack->Bottom();
nCardPos = 0;
while (pCard != nullptr) {
if (pCard->m_pSprite != nullptr) {
pCard->m_pSprite->RefreshSprite(pDC);
}
pCard = pCard->m_pNextCard;
nCardPos++;
}
(void)nCardPos; // avoid unused variable warning
}
CCard *CPaint::IsOnCard(CPoint cPoint) {
if ((m_pSprite = (OSpr *) m_pSprite->Touched(cPoint)) == nullptr)
return nullptr;
return m_pSprite->m_cCard->m_pStack->Top();
}
void CPaint::MoveCard(CDC *pDC, CCard *pCard, CPoint point) {
point.x -= pCard->m_pSprite->GetHotspot().x; // causes the point to appear in the
point.y -= pCard->m_pSprite->GetHotspot().y; // center of the card.
pCard->m_pSprite->PaintSprite(pDC, point);
}
void CPaint::UpdateCard(CDC *pDC, CCard *pCard) {
pCard->m_pSprite->PaintSprite(pDC, pCard->m_cOrigin); // paint card @ cur pos
}
void CPaint::FlipCard(CDC *pDC, CCard *pCard) {
/**********************************
* Get rid of current card bitmap. *
**********************************/
pCard->m_pSprite->RefreshBackground(pDC); // ...repaint background
pCard->m_pSprite->UnlinkSprite(); // unlink from refresh chain
delete pCard->m_pSprite;
/******************************************************************
* Reverse card. If it is a back, flip it forward, and vise versa. *
******************************************************************/
pCard->m_pSprite = new OSpr();
if (pCard->m_bIsBack == true) {
(*m_cCardSet[pCard->GetValue()]).DuplicateSprite(pDC, (CSprite*) pCard->m_pSprite);
pCard->m_bIsBack = false;
} else {
(*m_cCardSet[m_nCardBack]).DuplicateSprite(pDC, (CSprite*) pCard->m_pSprite);
pCard->m_bIsBack = true;
}
pCard->m_pSprite->LinkSprite();
pCard->m_pSprite->m_cCard = pCard; // update internal rep
}
/*****************************************************************
*
* Stack
*
* FUNCTIONAL DESCRIPTION:
*
* Indents top card properly relative to it's current stack.
* Assigns pCard->m_cOrigin to correct position.
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CPaint::Stack(CDC *pDC, CCard *pCard, int nSize) {
int i;
if (pCard == nullptr)
return;
if (nSize == -1) { // funct overloaded?
i = pCard->m_pStack->Size() - 1;// no, use stack size info
} else {
i = nSize; // yes, use info from param
}
switch (pCard->m_pStack->GetID()) { // Update card visual coordinates
case fnd:
case stock:
pCard->m_cOrigin = pCard->m_pStack->m_cRect.TopLeft();
pCard->m_cOrigin.x += ((int) i / STACK_INDENT) * STACK_DX;
pCard->m_cOrigin.y += ((int) i / STACK_INDENT) * STACK_DY;
break;
case used:
if (pCard->m_pStack->Bottom() == pCard) // bottom card?
m_nUsedInd = 0; // reset stack offset counter
pCard->m_cOrigin = pCard->m_pStack->m_cRect.TopLeft();
pCard->m_cOrigin.x += ((int) m_nUsedInd % USED_INDENT) * USED_DX;
pCard->m_cOrigin.y += ((int) m_nUsedInd % USED_INDENT) * USED_DY;
m_nUsedInd++;
break;
default:
if (pCard->m_pPrevCard != nullptr) { // card face req pos?
if (pCard->m_pPrevCard->m_bIsBack == false) {
pCard->m_cOrigin.x = pCard->m_pPrevCard->m_cOrigin.x + STACK_FACE_DX;
pCard->m_cOrigin.y = pCard->m_pPrevCard->m_cOrigin.y + STACK_FACE_DY;
break;
} // end if
}
//
// Card back requires positioning
//
pCard->m_cOrigin = pCard->m_pStack->m_cRect.TopLeft();
pCard->m_cOrigin.x += ((int) i / TAB_INDENT) * TAB_DX;
pCard->m_cOrigin.y += ((int) i / TAB_INDENT) * TAB_DY;
break;
}
pCard->m_pSprite->PaintSprite(pDC, pCard->m_cOrigin);
}
/*****************************************************************
*
* IsNewBack
*
* FUNCTIONAL DESCRIPTION:
*
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
bool CPaint::IsNewBack(int nBack) {
if (m_nCardBack == nBack) { // any change?
return false;
} else {
return true;
}
}
/*****************************************************************
*
* ChangeBack
*
* FUNCTIONAL DESCRIPTION:
*
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CPaint::ChangeBack(CDC *pDC, CBoard *pBoard, int nBack) {
int i;
CStack *pStack;
CCard *pCard;
if (m_nCardBack == nBack) { // any change?
return; // no - just return
} else {
m_nCardBack = nBack;
}
for (i = fnd; i <= used; i++) { // refresh tableau
pStack = pBoard->GetStack((loc) i);
pCard = pStack->Bottom();
while (pCard != nullptr) {
if (pCard->m_bIsBack == false) {
pCard = pCard->m_pNextCard;
continue;
}
pCard->m_pSprite->UnlinkSprite(); // unlink from refresh chain
delete pCard->m_pSprite;
pCard->m_pSprite = new OSpr();
(*m_cCardSet[m_nCardBack]).DuplicateSprite(pDC, (CSprite*) pCard->m_pSprite);
pCard->m_pSprite->LinkSprite();
pCard->m_pSprite->SetPosition(pCard->m_cOrigin);
pCard->m_pSprite->m_cCard = pCard; // update internal rep
pCard = pCard->m_pNextCard;
} // end while
} // end for
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,121 @@
/* 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 HODJNPODJ_BARBERSHOP_PAINT_H
#define HODJNPODJ_BARBERSHOP_PAINT_H
#include "bagel/hodjnpodj/barbershop/deck.h"
#include "bagel/hodjnpodj/barbershop/card.h"
#include "bagel/hodjnpodj/barbershop/stack.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define STD_CARD_WTH 72 // standard card width (x-val)
#define STD_CARD_HEI 97 // standard card height (y-val)
#define STD_HALF_WTH 37
#define STD_HALF_HEI 48
#define BITMAP_WTH 119
#define BITMAP_HEI 84
#define FND_LEF 500 // Foundation rect
#define FND_TOP 200
#define FND_RIG (FND_LEF + BITMAP_WTH)
#define FND_BOT (FND_TOP + BITMAP_HEI)
#define TAB_LEF 60 // Tableau rect
#define TAB_TOP 300
#define TAB_RIG (TAB_LEF + STD_CARD_WTH)
#define TAB_BOT (TAB_TOP + STD_CARD_HEI)
#define TAB_OFFSET 110 // offset from one tab stack to next
#define TAB_INDENT 1 // # of cards before next card is shifted
#define TAB_DX -2 // how much to shift card right/left
#define TAB_DY 2 // how much shift up/down
#define STACK_INDENT 5 // # of cards before next card is shifted
#define STACK_DX 0 // how much to shift card right/left
#define STACK_DY -2 // how much shift up/down
#define STACK_FACE_DX -7 // for Tableau face card shifting
#define STACK_FACE_DY 15
#define STOC_LEF 110 // Stock stack rect
#define STOC_TOP 200
#define STOC_RIG (STOC_LEF + BITMAP_WTH)
#define STOC_BOT (STOC_TOP + BITMAP_HEI)
#define USED_OFFSET BITMAP_WTH // Used stack offset from stock stack
#define USED_INDENT 3 // # of cards before next card is shifted
#define USED_DX 20 // how much to shift card right/left
#define USED_DY 0 // how much shift up/down
#define DECK_RES_ID 100 // corresp to crypt.rc alphabet id's
#define CARD_SET (DECK + 2) // 62 cards, 2 reverse sides
#define CARD_BACK1 DECK // reverse side of card #1
#define CARD_BACK2 DECK + 1 // reverse side of card #2
#define CARD_HOT_X 62 // Hotspot info for card positioning/moving
#define CARD_HOT_Y 41
#define CARDS_PER_COL 8 // amount of cards in the column for of the deck bitmap
#define CARDS_PER_ROW 8 // amount of cards in the row for of the deck bitmap
#define CARD_BACK1A_BMP "art\\card-bk1.bmp" // card back option #1
#define CARD_BACK2A_BMP "art\\card-bk2.bmp" // card back option #2
#define CARD_BACK1B_BMP "art\\card-bk3.bmp" // card back option #1
#define CARD_BACK2B_BMP "art\\card-bk4.bmp" // card back option #2
class CPaint {
private: // vars
OSpr *m_cCardSet[CARD_SET] = {};
public: // func
CPaint(CDC*);
~CPaint();
void Board(CDC*, CBoard*);
void Refresh(CDC*, CBoard*);
CCard *IsOnCard(CPoint);
void MoveCard(CDC*, CCard*, CPoint);
void UpdateCard(CDC*, CCard*);
void FlipCard(CDC*, CCard*);
void Stack(CDC*, CCard*, int nSize = -1);
bool IsNewBack(int);
void ChangeBack(CDC*, CBoard*, int);
public: // vars
OSpr *m_pSprite = nullptr;
CRect m_cFound;
CRect m_cTab[TAB_COUNT];
CRect m_cStock;
CRect m_cUsed;
int m_nUsedInd = 0;
int m_nCardBack = 0;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

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 HODJNPODJ_BARBERSHOP_RESOURCE_H
#define HODJNPODJ_BARBERSHOP_RESOURCE_H
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define HILITE_BORDER 3
#define INI_SECTION "Barbershop"
#define INI_LETTERSSOLVED "LettersSolved"
#define LSLVD_DEFAULT 6
#define MIN_LSLVD 0
#define MAX_LSLVD 20
#define INI_TIME "Time"
#define TIME_DEFAULT 180
#define MIN_TIME 15
#define MAX_TIME 601
#define INI_REC "Record"
#define REC_DEFAULT 0
#define CRYPT_RECS 200
//{{NO_DEPENDENCIES}}
// App Studio generated include file.
// Used by USERCFG.RC
//
#define IDD_RULES_DIALOG 900
#define IDC_RULES_OKAY 900
#define IDC_RULES_ARROWDN 901
#define IDC_RULES_ARROWUP 902
#define IDC_RULES_INVALID 903
} // namespace Barbershop
} // namespace HodjNPodj
} // 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/barbershop/stack.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
CStack::CStack(CRect cRect, int nID) {
m_pTopCard = nullptr;
m_pBottomCard = nullptr;
m_nID = nID;
m_nSize = 0;
m_cRect = cRect;
}
CStack::~CStack() {
}
void CStack::Reset() {
m_pTopCard = nullptr;
m_pBottomCard = nullptr;
m_nSize = 0;
}
void CStack::Push(CCard *pCard) {
if (pCard == nullptr)
return;
/*********************************************************
* Update card pointers aligning them with current stack. *
*********************************************************/
pCard->m_pPrevCard = m_pTopCard; // link new top prev to old top card
pCard->m_pNextCard = nullptr; // new top next card now does not point anywhere
pCard->m_pStack = this; // reassign proper stack location
/*************************
* Update stack pointers. *
*************************/
if (m_pTopCard != nullptr)
m_pTopCard->m_pNextCard = pCard; // create forward chain for next card
m_pTopCard = pCard; // link old top card to new top
if (m_pBottomCard == nullptr)
m_pBottomCard = pCard;
m_nSize++;
}
CCard *CStack::Pop() {
CCard *pReturnCard;
/**************************************************
* Undo any links of current card to other stacks. *
**************************************************/
pReturnCard = m_pTopCard;
if (m_pTopCard == nullptr) {
m_nSize = 0;
return nullptr;
}
if (m_pTopCard->m_pPrevCard != nullptr) {
m_pTopCard->m_pPrevCard->m_pNextCard = nullptr;
m_pTopCard = m_pTopCard->m_pPrevCard;
if (m_pTopCard->m_pNextCard != nullptr)
m_pTopCard->m_pNextCard->m_pPrevCard = m_pTopCard->m_pPrevCard; // make cur prev card point to prev of prev card :^) (if any)
m_nSize--;
} else {
m_pTopCard = nullptr;
m_pBottomCard = nullptr;
m_nSize = 0;
}
return pReturnCard;
}
void CStack::Unlink(CCard *pCard) {
/**************************************************
* Undo any links of current card to other stacks. *
**************************************************/
if (pCard->m_pNextCard != nullptr) {
pCard->m_pNextCard->m_pPrevCard = pCard->m_pPrevCard; // make cur prev card point to prev of prev card :^) (if any)
pCard->m_pNextCard = nullptr;
}
if (pCard->m_pPrevCard != nullptr) {
pCard->m_pPrevCard->m_pNextCard = pCard->m_pNextCard; // make cur of prev of next pointer point to next of the next (if any)
this->m_pTopCard = pCard->m_pPrevCard; // Top of stack points to the prev card
pCard->m_pPrevCard = nullptr; // clear the card "prev card" pointer
} else {
m_pTopCard = nullptr;
m_pBottomCard = nullptr;
}
/**************************************************
* Card's stack pointer should not point anywhere. *
**************************************************/
pCard->m_pStack = nullptr; // clear card "stack" pointer
}
int CStack::Size() {
return m_nSize;
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,75 @@
/* 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 HODJNPODJ_BARBERSHOP_STACK_H
#define HODJNPODJ_BARBERSHOP_STACK_H
#include "bagel/hodjnpodj/barbershop/card.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define STACKS 8
class CStack {
private: // vars
int m_nID;
CCard *m_pTopCard;
CCard *m_pBottomCard;
int m_nSize;
public: // functions
CStack(CRect, int nID);
~CStack();
void Reset();
void Unlink(CCard*);
void Push(CCard*);
CCard *Pop();
CCard *Top() const {
return m_pTopCard;
}
CCard *Bottom() const {
return m_pBottomCard;
}
bool IsEmpty() const {
return (bool)(m_pTopCard == nullptr);
}
int GetID() const {
return m_nID;
}
bool IsTab() {
return (bool)(m_nID >= tab && m_nID < stock);
}
int Size();
public:
CRect m_cRect;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/barbershop/stats.h"
#include "bagel/hodjnpodj/barbershop/resource.h"
#include "bagel/hodjnpodj/hodjnpodj.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
CStats::CStats() {
m_pTime = nullptr;
m_pScore = nullptr;
m_nLettersSolved = GetPrivateProfileInt(
INI_SECTION,
INI_LETTERSSOLVED,
LSLVD_DEFAULT,
INI_FILENAME
);
if (m_nLettersSolved < MIN_LSLVD || m_nLettersSolved > MAX_LSLVD)
m_nLettersSolved = LSLVD_DEFAULT;
m_nScore = 0;
m_nTime = GetPrivateProfileInt(
INI_SECTION,
INI_TIME,
TIME_DEFAULT,
INI_FILENAME
);
if (m_nTime < MIN_TIME || m_nTime > MAX_TIME)
m_nTime = TIME_DEFAULT;
m_nCountDown = m_nTime;
m_nIsUsedGram = GetPrivateProfileInt(
INI_SECTION,
INI_REC,
REC_DEFAULT,
INI_FILENAME
);
}
CStats::~CStats() {
if (m_pScore != nullptr) {
delete m_pScore;
m_pScore = nullptr;
}
if (m_pTime != nullptr) {
delete m_pTime;
m_pTime = nullptr;
}
}
int CStats::ResetGame() {
//char chResetUsedGram;
int nID;
//int i;
/*************************
* Reset crytogram stats. *
*************************/
m_nCountDown = m_nTime;
m_nScore = 0;
do { // Get random unused cryptogram
nID = brand() % CRYPT_RECS;
} while (m_nIsUsedGram == nID);
m_nIsUsedGram = nID; // Mark as used
WritePrivateProfileString(
INI_SECTION,
INI_REC,
Common::String::format("%d", m_nIsUsedGram).c_str(),
INI_FILENAME
); // Save used list back
return nID;
}
void CStats::SaveStats(int nLttrsSlvd, int nTime) {
m_nLettersSolved = nLttrsSlvd;
m_nTime = nTime;
WritePrivateProfileString(
INI_SECTION,
INI_LETTERSSOLVED,
Common::String::format("%d", m_nLettersSolved).c_str(),
INI_FILENAME
);
WritePrivateProfileString(
INI_SECTION,
INI_TIME,
Common::String::format("%d", m_nTime).c_str(),
INI_FILENAME
);
}
} // namespace Barbershop
} // namespace HodjNPodj
} // 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 HODJNPODJ_BARBERSHOP_STATS_H
#define HODJNPODJ_BARBERSHOP_STATS_H
#include "bagel/hodjnpodj/hnplibs/text.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define STATS_COLOR RGB(255,255,255)
#define SCORE_FACTOR 2
#define SCORE_JACKPOT 100
class CStats {
public:
CStats();
~CStats();
void SaveStats(int nLttrsSlvd, int nTime);
int ResetGame();
CText *m_pScore;
CText *m_pTime;
int m_nLettersSolved;
int m_nScore;
int m_nTime;
int m_nCountDown;
char m_nIsUsedGram;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/barbershop/undo.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
/*****************************************************************
*
* [function name]
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
CUndo::CUndo() {
m_cUndoRect = CRect(
UNDO_LEF,
UNDO_TOP,
UNDO_RIG,
UNDO_BOT
);
m_pStack = nullptr;
m_pCard = nullptr;
m_nStock = NONE;
}
/*****************************************************************
*
* [function name]
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
CUndo::~CUndo() {
}
/*****************************************************************
*
* [function name]
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CUndo::Record(CStack *pStack, CCard *pCard) {
m_pStack = pStack;
m_pCard = pCard;
m_nStock = NONE;
}
/*****************************************************************
*
* [function name]
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CUndo::Record(int nCardsFlipped) {
m_nStock = nCardsFlipped;
m_pStack = nullptr;
m_pCard = nullptr;
}
/*****************************************************************
*
* Reset
*
* FUNCTIONAL DESCRIPTION:
*
* Resets undo parameters
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
void CUndo::Reset() {
m_pStack = nullptr;
m_pCard = nullptr;
m_nStock = NONE;
}
/*****************************************************************
*
* Undo
*
* FUNCTIONAL DESCRIPTION:
*
* Puts card back into original position.
* Returns true if undo was possible, else false.
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
bool CUndo::Undo(CDC *pDC, CBoard *pBoard, CPaint *pPaint) {
CCard *pCard;
CPoint cPos;
int i;
if (m_nStock != NONE) { // undo stock card flip?
for (i = 0; i < m_nStock; i++) {
//
// update interal representation
//
pCard = pBoard->GetStack((loc) used)->Pop();
pBoard->GetStack((loc) stock)->Push(pCard);
//
// update visual rep
//
pPaint->FlipCard(pDC, pCard);
pPaint->Stack(pDC, pCard);
pPaint->m_nUsedInd--;
} // end for
Reset(); // clear undo
return true;
} // end if
if (m_pStack == nullptr) // basic card undo?
return false; // No - nothing can be undone
m_pCard->m_pStack->Pop(); // undo move in internal rep
m_pStack->Push(m_pCard); // undo move in internal rep
if (m_pStack->GetID() == used) { // card in used stack?
//
// messy code to handle special visual used stacking order
//
if (m_pCard->m_pPrevCard == nullptr) {
pPaint->m_nUsedInd = 0;
} else {
if (m_pCard->m_pPrevCard->m_cOrigin.x == m_pCard->m_pStack->m_cRect.TopLeft().x) {
pPaint->m_nUsedInd = 1;
} else if (m_pCard->m_pPrevCard->m_cOrigin.x == m_pCard->m_pStack->m_cRect.TopLeft().x + (1 * USED_DX)) {
pPaint->m_nUsedInd = 2;
} else {
pPaint->m_nUsedInd = 0;
} // end if
} // end if
pPaint->Stack(pDC, m_pCard); // draw card apro stack
pPaint->m_nUsedInd = 0;
} else {
pPaint->Stack(pDC, m_pCard); // draw card apro stack
} // end if
Reset(); // clear undo
return true;
}
} // namespace Barbershop
} // namespace HodjNPodj
} // 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 HODJNPODJ_BARBERSHOP_UNDO_H
#define HODJNPODJ_BARBERSHOP_UNDO_H
#include "bagel/hodjnpodj/barbershop/paint.h"
#include "bagel/hodjnpodj/barbershop/board.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
constexpr int NONE = -1;
#define UNDO_LEF 432 // Undo hotspot rect
#define UNDO_TOP 80
#define UNDO_RIG (UNDO_LEF + 98)
#define UNDO_BOT (UNDO_TOP + 94)
class CUndo {
public:
CUndo();
~CUndo();
void Record(CStack*, CCard*);
void Record(int);
void Reset();
bool Undo(CDC*, CBoard*, CPaint*);
CRect m_cUndoRect;
private:
CStack *m_pStack;
CCard *m_pCard;
int m_nStock;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,232 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/bitmaps.h"
#include "bagel/hodjnpodj/barbershop/usercfg.h"
#include "bagel/hodjnpodj/hnplibs/menures.h"
#include "bagel/hodjnpodj/barbershop/paint.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define ID_RESET 104
#define ID_LIMIT 105
#define PAGE_SIZE 10
// globals!!
//
//
extern const char *INI_SECTION;
extern CPalette *pGamePalette;
extern LPGAMESTRUCT pGameParams;
extern int g_nCardBack;
CUserCfgDlg::CUserCfgDlg(CWnd *pParent, CPalette *pPalette, unsigned int nID)
: CBmpDialog(pParent, pPalette, nID, ".\\ART\\SSCROLL.BMP") {
m_cRectCardBack1 = CRect(CBCK_RECT1_LEFT - DELTA, CBCK_RECT1_TOP - DELTA, CBCK_RECT1_RIG + DELTA, CBCK_RECT1_BOT + DELTA);
m_cRectCardBack2 = CRect(CBCK_RECT2_LEFT - DELTA, CBCK_RECT2_TOP - DELTA, CBCK_RECT2_RIG + DELTA, CBCK_RECT2_BOT + DELTA);
m_nCardBack = g_nCardBack;
DoModal();
}
void CUserCfgDlg::DoDataExchange(CDataExchange *pDX) {
CDialog::DoDataExchange(pDX);
}
bool CUserCfgDlg::OnInitDialog() {
CDC *pDC = GetDC();
CRect tmpRect;
CBmpDialog::OnInitDialog();
m_bSave = false;
if ((m_ctextBox = new CText) != nullptr) {
bool bAssertCheck;
tmpRect.SetRect(TEXT_LEFT, TEXT_TOP, TEXT_RIG, TEXT_BOT);
bAssertCheck = (*m_ctextBox).SetupText(pDC, pGamePalette, &tmpRect, JUSTIFY_CENTER);
ASSERT(bAssertCheck); // initialize the text objext
} // end if
if ((m_pOKButton = new CColorButton) != nullptr) { // build a color OK button
(*m_pOKButton).SetPalette(pGamePalette); // set the palette to use
(*m_pOKButton).SetControl(IDOK, this); // tie to the dialog control
} // end if
ReleaseDC(pDC);
return true;
}
void CUserCfgDlg::OnPaint() {
CDC *pDC = nullptr;
char msg[64];
bool bAssertCheck;
CBmpDialog::OnPaint();
pDC = GetDC();
if (m_nCardBack == CARD_BACK1) { // card back painting
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK1B_BMP, CBCK_RECT1_LEFT, CBCK_RECT1_TOP, CBCK_RECT1_RIG - CBCK_RECT1_LEFT, CBCK_RECT1_BOT - CBCK_RECT1_TOP);
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK2A_BMP, CBCK_RECT2_LEFT, CBCK_RECT2_TOP, CBCK_RECT2_RIG - CBCK_RECT2_LEFT, CBCK_RECT2_BOT - CBCK_RECT2_TOP);
} else {
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK1A_BMP, CBCK_RECT1_LEFT, CBCK_RECT1_TOP, CBCK_RECT1_RIG - CBCK_RECT1_LEFT, CBCK_RECT1_BOT - CBCK_RECT1_TOP);
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK2B_BMP, CBCK_RECT2_LEFT, CBCK_RECT2_TOP, CBCK_RECT2_RIG - CBCK_RECT2_LEFT, CBCK_RECT2_BOT - CBCK_RECT2_TOP);
} // end if
Common::sprintf_s(msg, "Select a card back"); // top message
bAssertCheck = (*m_ctextBox).DisplayString(pDC, msg, FONT_SIZE, FW_BOLD, RGBCOLOR_BLACK);
ASSERT(bAssertCheck);
ReleaseDC(pDC);
}
void CUserCfgDlg::OnLButtonUp(unsigned int nFlags, CPoint point) {
CDC *pDC = GetDC();
if (
m_cRectCardBack1.PtInRect(point) == true &&
m_nCardBack != CARD_BACK1
) {
// update visual image
//
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK1B_BMP, CBCK_RECT1_LEFT, CBCK_RECT1_TOP, CBCK_RECT1_RIG - CBCK_RECT1_LEFT, CBCK_RECT1_BOT - CBCK_RECT1_TOP);
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK2A_BMP, CBCK_RECT2_LEFT, CBCK_RECT2_TOP, CBCK_RECT2_RIG - CBCK_RECT2_LEFT, CBCK_RECT2_BOT - CBCK_RECT2_TOP);
m_nCardBack = CARD_BACK1;
} else if (
m_cRectCardBack2.PtInRect(point) == true &&
m_nCardBack != CARD_BACK2
) {
// update visual image
//
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK1A_BMP, CBCK_RECT1_LEFT, CBCK_RECT1_TOP, CBCK_RECT1_RIG - CBCK_RECT1_LEFT, CBCK_RECT1_BOT - CBCK_RECT1_TOP);
PaintMaskedDIB(pDC, pGamePalette, CARD_BACK2B_BMP, CBCK_RECT2_LEFT, CBCK_RECT2_TOP, CBCK_RECT2_RIG - CBCK_RECT2_LEFT, CBCK_RECT2_BOT - CBCK_RECT2_TOP);
m_nCardBack = CARD_BACK2;
} // end if
ReleaseDC(pDC);
}
void CUserCfgDlg::OnOK() {
ValidateRect(nullptr);
g_nCardBack = m_nCardBack;
EndDialog(IDOK);
}
void CUserCfgDlg::OnCancel() {
ValidateRect(nullptr);
EndDialog(IDCANCEL);
}
void CUserCfgDlg::OnClose() {
ValidateRect(nullptr);
if (m_pOKButton != nullptr) { // release button
delete m_pOKButton;
m_pOKButton = nullptr;
}
if (m_ctextBox != nullptr) {
delete m_ctextBox;
m_ctextBox = nullptr;
} // end if
}
BEGIN_MESSAGE_MAP(CUserCfgDlg, CBmpDialog)
ON_WM_LBUTTONUP()
ON_WM_CLOSE()
ON_WM_PAINT()
END_MESSAGE_MAP()
/*****************************************************************
*
* MyFocusRect( CDC *pDC, CRect rect, int nDrawMode )
*
* FUNCTIONAL DESCRIPTION:
*
* Draws a rectangle which inverts the current pixels,
* thereby delineating the current area of focus.
*
* FORMAL PARAMETERS:
*
* CDC *pDC The Device context in which the FocusRect is to be drawn
* CRect rect The CRect object holding the location of the FocusRect
*
* IMPLICIT INPUT PARAMETERS:
*
* pMyPen and pMyBrush, global pointers to the Pen and Brush used
*
* IMPLICIT OUTPUT PARAMETERS:
*
* none
*
* RETURN VALUE:
*
* void
*
****************************************************************/
void CUserCfgDlg::MyFocusRect(CDC *pDC, CRect rect, int nDrawMode, COLORREF rgbColor) {
CBrush *pMyBrush = nullptr; // New Brush
CBrush *pOldBrush = nullptr; // Pointer to old brush
CPen *pMyPen = nullptr; // New Pen
CPen *pOldPen = nullptr; // Pointer to old pen
CPalette *pPalOld = nullptr; // Pointer to old palette
int OldDrawMode; // Holder for old draw mode
pMyBrush = new CBrush(); // Construct new brush
pMyPen = new CPen(); // Construct new pen
LOGBRUSH lb; // log brush type
lb.lbStyle = BS_HOLLOW; // Don't fill in area
pMyBrush->CreateBrushIndirect(&lb); // Create a new brush
pMyPen->CreatePen(PS_INSIDEFRAME, DELTA, rgbColor); // Create a new pen
pPalOld = (*pDC).SelectPalette(pGamePalette, false); // Select in game palette
(*pDC).RealizePalette(); // Use it
pOldPen = pDC->SelectObject(pMyPen); // Select the new pen & save old
pOldBrush = pDC->SelectObject(pMyBrush); // Select the new brush & save old
OldDrawMode = pDC->SetROP2(nDrawMode); // Set pen mode, saving old state
pDC->Rectangle(rect); // Draw the Rectangle to the DC
pDC->SelectObject(pOldPen); // Select the old pen
pDC->SelectObject(pOldBrush); // Select the old brush
pDC->SetROP2(OldDrawMode); // Set pen mode back to old state
(*pDC).SelectPalette(pPalOld, false); // Select back the old palette
pMyBrush->DeleteObject();
delete pMyBrush;
pMyPen->DeleteObject();
delete pMyPen;
}
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,93 @@
/* 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 HODJNPODJ_BARBERSHOP_USERCFG_H
#define HODJNPODJ_BARBERSHOP_USERCFG_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/barbershop/main.h"
namespace Bagel {
namespace HodjNPodj {
namespace Barbershop {
#define RGBCOLOR_DARKRED RGB(0, 128, 0)
#define RGBCOLOR_BLACK RGB(0, 0, 0)
#define RGBCOLOR_WHITE RGB(255, 255, 255)
#define FONT_SIZE 16 // CText object font size
// CText message
#define TEXT_LEFT 20
#define TEXT_TOP 25
#define TEXT_RIG 220
#define TEXT_BOT 46
// card back rect 1
#define CBCK_RECT1_LEFT 40
#define CBCK_RECT1_TOP 55
#define CBCK_RECT1_RIG 110
#define CBCK_RECT1_BOT 125
// card back rect 2
#define CBCK_RECT2_LEFT 120
#define CBCK_RECT2_TOP 55
#define CBCK_RECT2_RIG 190
#define CBCK_RECT2_BOT 125
#define DELTA 0
#define IDD_USERCFG 100
class CUserCfgDlg : public CBmpDialog {
public:
CUserCfgDlg(CWnd *pParent = nullptr, CPalette *pPalette = nullptr, unsigned int = IDD_USERCFG);
protected:
virtual void DoDataExchange(CDataExchange *) override;
virtual bool OnInitDialog() override;
void OnClose();
void OnPaint();
void OnLButtonUp(unsigned int, CPoint);
void OnCancel() override;
void OnOK() override;
DECLARE_MESSAGE_MAP()
void MyFocusRect(CDC*, CRect, int nDrawMode, COLORREF);
private:
bool m_bSave = false; // True if should save theses values
CRect m_cRectCardBack1;
CRect m_cRectCardBack2;
unsigned int m_nCardBack = 0;
CColorButton *m_pOKButton = nullptr; // OKAY button on scroll
CText *m_ctextBox = nullptr;
};
} // namespace Barbershop
} // namespace HodjNPodj
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

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 HODJNPODJ_BATTLEFISH_BFISH_H
#define HODJNPODJ_BATTLEFISH_BFISH_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
#include "bagel/hodjnpodj/hnplibs/sprite.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/boflib/error.h"
#include "bagel/boflib/sound.h"
namespace Bagel {
namespace HodjNPodj {
namespace Battlefish {
#define GRID_ROWS 8
#define GRID_COLS 8
#define MAX_FISH 4
#define MAX_FISH_SIZE 2*3
#define MAX_TURNS MAX_FISH
typedef struct {
POINT nLoc[MAX_FISH_SIZE + 1];
byte life;
} FISH;
class CBFishWindow : public CFrameWnd {
public:
CBFishWindow();
void PlayGame();
void PaintScreen();
void LoadIniSettings();
void SaveIniSettings();
protected:
void FlushInputEvents();
void GameReset();
void GamePause();
void GameResume();
void HandleError(ERROR_CODE);
void DeleteSprite(CSprite *);
ERROR_CODE RepaintSpriteList(CDC *);
ERROR_CODE LoadMasterSprites();
void ReleaseMasterSprites();
void PlaceUserFish();
void PlaceEnemyFish();
void RotateFish(int);
void AssignFishToGrid(int);
int GetEnemyGridIndex(CPoint);
int GetUserGridIndex(CPoint);
int GetFishIndex(CSprite *);
bool OkToPlaceFish(int, CPoint, bool);
void PlaceFish(int, CPoint);
int IndexToId(int);
int IdToIndex(int);
CPoint SnapToGrid(CPoint);
void UsersTurn(int);
void ComputersTurn();
int SelectRandomTarget();
int SelectBurningTarget();
int SelectBestFitTarget();
int FindNeighborTarget(int, int);
int FindTarget(int, int);
int FindMatch(int, int);
bool FishFits(int, int, int);
int GetNeighbors(int, int);
void CreatePlume(CPoint);
void CreateHarpoon(CPoint);
void SinkUserFish(int);
void SinkEnemyFish(int);
void PlaceTurnHarpoons();
void RemoveTurnHarpoon();
virtual bool OnCommand(WPARAM wParam, LPARAM lParam) override;
LRESULT OnMCINotify(WPARAM, LPARAM);
LRESULT OnMMIONotify(WPARAM, LPARAM);
void OnSoundNotify(CSound *);
void OnPaint();
void OnMouseMove(unsigned int, CPoint);
void OnRButtonDown(unsigned int, CPoint);
void OnLButtonDown(unsigned int, CPoint);
void OnLButtonUp(unsigned int, CPoint);
void OnSysChar(unsigned int, unsigned int, unsigned int);
void OnSysKeyDown(unsigned int, unsigned int, unsigned int);
void OnKeyDown(unsigned int, unsigned int, unsigned int);
void OnActivate(unsigned int, CWnd *, bool) override;
void OnClose();
DECLARE_MESSAGE_MAP()
// Data Members
//
byte m_nUserGrid[GRID_ROWS][GRID_COLS] = {};
byte m_nEnemyGrid[GRID_ROWS][GRID_COLS] = {};
FISH m_aEnemyFishInfo[MAX_FISH] = {};
FISH m_aUserFishInfo[MAX_FISH] = {};
CRect m_rNewGameButton;
CRect m_rEndPlacement;
CPoint m_cLastPoint;
CSprite *m_pHarpoons[MAX_TURNS] = {};
CSprite *m_pFish[MAX_FISH] = {};
CSprite *m_pEnemyFish[MAX_FISH] = {};
CSprite *m_pMasterHit = nullptr;
CSprite *m_pMasterMiss = nullptr;
CSprite *m_pMasterHarpoon = nullptr;
CSprite *m_pDragFish = nullptr;
CSprite *m_pScrollSprite = nullptr;
CSprite *m_pOctopus = nullptr;
CPalette *m_pGamePalette = nullptr;
CSound *m_pSoundTrack = nullptr;
CText *m_pTxtClickHere = nullptr;
int m_nEnemyFish = 0;
int m_nUserFish = 0;
int m_nTurns = 0;
int m_nDifficultyLevel = 0;
bool m_bGameActive = false;
bool m_bPause = false;
bool m_bUserEditMode = false;
bool m_bMovingFish = false;
bool m_bLastRotated = false;
bool m_bStillCheck = false;
bool m_bUsersTurn = false;
bool m_bInMenu = false;
};
} // namespace Battlefish
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,98 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/hodjnpodj/battlefish/bfish.h"
namespace Bagel {
namespace HodjNPodj {
namespace Battlefish {
HINSTANCE hDLLInst;
HINSTANCE hExeInst;
extern LPGAMESTRUCT pGameParams;
// global the pointer to the your game's main window
HWND ghParentWnd;
/////////////////////////////////////////////////////////////////////////////
// Public C interface
/*****************************************************************
*
* RunBFish
*
* FUNCTIONAL DESCRIPTION:
*
* This is the API function for the DLL. It is what the calling app
* calls to invoke poker
*
* FORMAL PARAMETERS:
*
* hParentWnd, lpGameInfo
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
HWND FAR PASCAL RunBFish(HWND hParentWnd, LPGAMESTRUCT lpGameInfo) {
CBFishWindow *pMain;
pGameParams = lpGameInfo;
// invoke your game here by creating a pGame for your main window
// look at the InitInstance for your game for this
ghParentWnd = hParentWnd;
if ((pMain = new CBFishWindow) != nullptr) {
pMain->ShowWindow(SW_SHOWNORMAL);
pMain->UpdateWindow();
pMain->SetActiveWindow();
if (pGameParams->bPlayingMetagame)
pMain->PlayGame();
}
// these must be set in this function
hDLLInst = (HINSTANCE)GetWindowWord(pMain->m_hWnd, GWW_HINSTANCE);
hExeInst = (HINSTANCE)GetWindowWord(hParentWnd, GWW_HINSTANCE);
return pMain->m_hWnd; // return the m_hWnd of your main game window
}
} // namespace Battlefish
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,33 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
namespace Bagel {
namespace HodjNPodj {
namespace Battlefish {
extern HWND FAR PASCAL RunBFish(HWND hParentWnd, LPGAMESTRUCT lpGameInfo);
} // namespace Battlefish
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,407 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/globals.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
#include "bagel/hodjnpodj/battlefish/usercfg.h"
namespace Bagel {
namespace HodjNPodj {
namespace Battlefish {
#define ID_RESET 104
#define ID_LIMIT 105
#define ID_PLAYER 106
#define ID_COMPUTER 107
#define PAGE_SIZE 1
static const char *pszDiffLevel[DIFF_MAX + 1] = {
"Wimpy",
"Average",
"Hefty"
};
extern const char *INI_SECTION;
CUserCfgDlg::CUserCfgDlg(CWnd *pParent, CPalette *pPalette, unsigned int nID)
: CBmpDialog(pParent, pPalette, nID, ".\\ART\\SSCROLL.BMP") {
m_pOKButton = nullptr;
m_pCancelButton = nullptr;
m_pDefaultsButton = nullptr;
m_pUserButton = nullptr;
m_pCompButton = nullptr;
DoModal();
}
bool CUserCfgDlg::OnInitDialog() {
CRect tmpRect;
CDC *pDC;
CBmpDialog::OnInitDialog();
m_pTxtLevel = nullptr;
m_pTxtDifficulty = nullptr;
tmpRect.SetRect(22, 135, 122, 155);
if ((m_pScrollBar = new CScrollBar) != nullptr) {
m_pScrollBar->Create(WS_VISIBLE | WS_CHILD | SBS_HORZ | SBS_BOTTOMALIGN, tmpRect, this, ID_LIMIT);
m_pScrollBar->SetScrollRange(DIFF_MIN, DIFF_MAX, true);
}
if ((pDC = GetDC()) != nullptr) {
tmpRect.SetRect(25, 111, 80, 131);
if ((m_pTxtLevel = new CText) != nullptr) {
m_pTxtLevel->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
}
tmpRect.SetRect(81, 111, 146, 131);
if ((m_pTxtDifficulty = new CText) != nullptr) {
m_pTxtDifficulty->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
}
tmpRect.SetRect(25, 20, 150, 40);
if ((m_pTxtOrder = new CText) != nullptr) {
m_pTxtOrder->SetupText(pDC, m_pPalette, &tmpRect, JUSTIFY_LEFT);
}
ReleaseDC(pDC);
}
if ((m_pOKButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*m_pOKButton).SetPalette(m_pPalette); // set the palette to use
(*m_pOKButton).SetControl(IDOK, this); // tie to the dialog control
}
if ((m_pCancelButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*m_pCancelButton).SetPalette(m_pPalette); // set the palette to use
(*m_pCancelButton).SetControl(IDCANCEL, this); // tie to the dialog control
}
if ((m_pDefaultsButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*m_pDefaultsButton).SetPalette(m_pPalette); // set the palette to use
(*m_pDefaultsButton).SetControl(ID_RESET, this); // tie to the dialog control
}
if ((m_pUserButton = new CRadioButton) != nullptr) {
tmpRect.SetRect(21, 32, 75, 45);
//m_pUserButton->Create("Human", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP | BS_OWNERDRAW, tmpRect, this, ID_PLAYER);
m_pUserButton->SetPalette(m_pPalette);
m_pUserButton->SetControl(ID_PLAYER, this);
}
if ((m_pCompButton = new CRadioButton) != nullptr) {
tmpRect.SetRect(21, 45, 75, 58);
//m_pUserButton->Create("Computer", BS_AUTORADIOBUTTON | WS_TABSTOP | BS_OWNERDRAW, tmpRect, this, ID_COMPUTER);
m_pCompButton->SetPalette(m_pPalette);
m_pCompButton->SetControl(ID_COMPUTER, this);
}
m_bSave = false;
LoadIniSettings();
PutDlgData();
return true;
}
void CUserCfgDlg::PutDlgData() {
m_pScrollBar->SetScrollPos(m_nDifficultyLevel);
m_pUserButton->SetCheck(m_bUserGoesFirst);
m_pCompButton->SetCheck(!m_bUserGoesFirst);
}
void CUserCfgDlg::GetDlgData() {
m_nDifficultyLevel = m_pScrollBar->GetScrollPos();
m_bUserGoesFirst = false;
if (m_pUserButton->GetCheck() == 1)
m_bUserGoesFirst = true;
}
bool CUserCfgDlg::OnCommand(WPARAM wParam, LPARAM lParam) {
//
// respond to user
//
if (HIWORD(lParam) == BN_CLICKED) {
switch (wParam) {
case IDOK:
m_bSave = true;
ClearDialogImage();
EndDialog(IDOK);
return false;
case IDCANCEL:
ClearDialogImage();
EndDialog(IDCANCEL);
return false;
case ID_PLAYER:
m_bUserGoesFirst = true;
PutDlgData();
break;
case ID_COMPUTER:
m_bUserGoesFirst = false;
PutDlgData();
break;
/*
* reset params to default
*/
case ID_RESET:
m_nDifficultyLevel = DIFF_DEF;
m_bUserGoesFirst = TURN_DEF;
PutDlgData();
DispLimit();
break;
default:
break;
}
}
return CBmpDialog::OnCommand(wParam, lParam);
}
void CUserCfgDlg::OnHScroll(unsigned int nSBCode, unsigned int nPos, CScrollBar *pScroll) {
switch (nSBCode) {
case SB_LEFT:
m_nDifficultyLevel = DIFF_MIN;
break;
case SB_PAGELEFT:
m_nDifficultyLevel -= PAGE_SIZE;
break;
case SB_LINELEFT:
if (m_nDifficultyLevel > DIFF_MIN)
m_nDifficultyLevel--;
break;
case SB_RIGHT:
m_nDifficultyLevel = DIFF_MAX;
break;
case SB_PAGERIGHT:
m_nDifficultyLevel += PAGE_SIZE;
break;
case SB_LINERIGHT:
if (m_nDifficultyLevel < DIFF_MAX)
m_nDifficultyLevel++;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
m_nDifficultyLevel = nPos;
break;
default:
break;
}
if (m_nDifficultyLevel <= DIFF_MIN)
m_nDifficultyLevel = DIFF_MIN;
if (m_nDifficultyLevel > DIFF_MAX)
m_nDifficultyLevel = DIFF_MAX;
// can't access a null pointer
assert(pScroll != nullptr);
pScroll->SetScrollPos(m_nDifficultyLevel);
DispLimit();
}
/*****************************************************************
*
* LoadIniSettings
*
* FUNCTIONAL DESCRIPTION:
*
* Loads this game's parameters from .INI file
*
* FORMAL PARAMETERS:
*
* None
*
* RETURN VALUE:
*
* None
*
****************************************************************/
void CUserCfgDlg::LoadIniSettings() {
int nVal;
// Get the Difficulty level (0..2)
//
nVal = GetPrivateProfileInt(INI_SECTION, "DifficultyLevel", DIFF_DEF, INI_FILENAME);
m_nDifficultyLevel = nVal;
if (nVal < DIFF_MIN || nVal > DIFF_MAX)
m_nDifficultyLevel = DIFF_DEF;
// Get the UserGoesFirst option setting
//
nVal = GetPrivateProfileInt(INI_SECTION, "UserGoesFirst", TURN_DEF, INI_FILENAME);
m_bUserGoesFirst = (nVal == 0 ? false : true);
}
void CUserCfgDlg::SaveIniSettings() {
WritePrivateProfileString(INI_SECTION,
"DifficultyLevel",
Common::String::format("%d", m_nDifficultyLevel).c_str(),
INI_FILENAME);
WritePrivateProfileString(INI_SECTION,
"UserGoesFirst",
Common::String::format("%d", m_bUserGoesFirst).c_str(),
INI_FILENAME);
}
void CUserCfgDlg::OnPaint() {
CDC *pDC;
CBmpDialog::OnPaint();
if ((pDC = GetDC()) != nullptr) {
m_pTxtLevel->DisplayString(pDC, "Difficulty:", 14, TEXT_BOLD, RGB(0, 0, 0));
m_pTxtOrder->DisplayString(pDC, "Who goes first?", 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
}
DispLimit();
}
void CUserCfgDlg::OnDestroy() {
if (m_pOKButton != nullptr) { // release the button
delete m_pOKButton;
m_pOKButton = nullptr;
}
if (m_pCancelButton != nullptr) { // release the button
delete m_pCancelButton;
m_pCancelButton = nullptr;
}
if (m_pDefaultsButton != nullptr) { // release the button
delete m_pDefaultsButton;
m_pDefaultsButton = nullptr;
}
assert(m_pTxtDifficulty != nullptr);
if (m_pTxtDifficulty != nullptr) {
delete m_pTxtDifficulty;
m_pTxtDifficulty = nullptr;
}
assert(m_pTxtLevel != nullptr);
if (m_pTxtLevel != nullptr) {
delete m_pTxtLevel;
m_pTxtLevel = nullptr;
}
if (m_pTxtOrder != nullptr) {
delete m_pTxtOrder;
m_pTxtOrder = nullptr;
}
//
// de-allocate the scroll bar
//
assert(m_pScrollBar != nullptr);
if (m_pScrollBar != nullptr) {
delete m_pScrollBar;
m_pScrollBar = nullptr;
}
CBmpDialog::OnDestroy();
}
void CUserCfgDlg::ClearDialogImage() {
if (m_bSave) {
GetDlgData();
SaveIniSettings();
}
if (m_pCompButton != nullptr) {
delete m_pCompButton;
m_pCompButton = nullptr;
}
if (m_pUserButton != nullptr) {
delete m_pUserButton;
m_pUserButton = nullptr;
}
if (m_pOKButton != nullptr) { // release the button
delete m_pOKButton;
m_pOKButton = nullptr;
}
if (m_pCancelButton != nullptr) { // release the button
delete m_pCancelButton;
m_pCancelButton = nullptr;
}
if (m_pDefaultsButton != nullptr) { // release the button
delete m_pDefaultsButton;
m_pDefaultsButton = nullptr;
}
ValidateRect(nullptr);
}
void CUserCfgDlg::DispLimit() {
CDC *pDC;
if ((pDC = GetDC()) != nullptr) {
m_pTxtDifficulty->DisplayString(pDC, pszDiffLevel[m_nDifficultyLevel], 14, TEXT_BOLD, RGB(0, 0, 0));
ReleaseDC(pDC);
}
}
BEGIN_MESSAGE_MAP(CUserCfgDlg, CBmpDialog)
ON_WM_DESTROY()
ON_WM_HSCROLL()
ON_WM_PAINT()
END_MESSAGE_MAP()
} // namespace Battlefish
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,80 @@
/* 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 HODJNPODJ_BATTLEFISH_USERCFG_H
#define HODJNPODJ_BATTLEFISH_USERCFG_H
#include "bagel/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
#include "bagel/boflib/misc.h"
namespace Bagel {
namespace HodjNPodj {
namespace Battlefish {
#define IDD_USERCFG 100
#define DIFF_MIN 0
#define DIFF_MAX 2
#define DIFF_DEF 2
#define TURN_DEF false
class CUserCfgDlg : public CBmpDialog {
public:
CUserCfgDlg(CWnd *pParent = nullptr, CPalette *pPalette = nullptr, unsigned int = IDD_USERCFG);
protected:
virtual bool OnCommand(WPARAM, LPARAM) override;
virtual bool OnInitDialog() override;
void PutDlgData();
void GetDlgData();
void DispLimit();
void LoadIniSettings();
void SaveIniSettings();
void OnHScroll(unsigned int, unsigned int, CScrollBar *);
void OnDestroy();
void OnPaint();
void ClearDialogImage();
DECLARE_MESSAGE_MAP()
CColorButton *m_pOKButton = nullptr; // OKAY button on scroll
CColorButton *m_pCancelButton = nullptr; // Cancel button on scroll
CColorButton *m_pDefaultsButton = nullptr; // Defaults button on scroll
CRadioButton *m_pUserButton = nullptr;
CRadioButton *m_pCompButton = nullptr;
CText *m_pTxtDifficulty = nullptr;
CText *m_pTxtLevel = nullptr;
CText *m_pTxtOrder = nullptr;
CScrollBar *m_pScrollBar = nullptr;
unsigned int m_nDifficultyLevel = 0; // Difficulty level for BattleFish
bool m_bSave = false; // True if should save theses settings
bool m_bUserGoesFirst = false; // true if Human player goes 1st
};
} // namespace Battlefish
} // namespace HodjNPodj
} // namespace Bagel
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,171 @@
/* 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 HODJNPODJ_BEACON_BEACON_H
#define HODJNPODJ_BEACON_BEACON_H
#include "bagel/boflib/sound.h"
namespace Bagel {
namespace HodjNPodj {
namespace Beacon {
#define ABS(a) ( (a > 0) ? (a) : (-a) )
// Border info
#define TOP_BORDER 24 //25
#define BOTTOM_BORDER 16
#define SIDE_BORDER 16
#define BEACON_TIMER 1
#define MIN_SPEED 0
#define MAX_SPEED 2
#define SPEED_BASE 70
#define SPEED_STEP 10
#define NUM_BEAMS 120
#define CHANGE_BEAM 144
#define START_ENTRY 55 // Starting entry of available palette slots
#define BUTTON_ENTRY 176 // First entry of the Button palette slots
#define GRID_WIDTH 8 //5 // Number of pixels
#define GRID_HEIGHT 8 //5
// Game playing area
#define ART_WIDTH 488
#define ART_HEIGHT 440
#define NUM_BUTTONS 16 // Number of buttons
#define NUM_COLUMNS (ART_WIDTH / GRID_WIDTH)
#define NUM_ROWS (ART_HEIGHT / GRID_HEIGHT)
// Lighthouse bitmap placement
#define LTHOUSE_OFFSET_X 20
#define LTHOUSE_OFFSET_Y 15
#define LTHOUSE_WIDTH 50
#define LTHOUSE_HEIGHT 70
// Start area
#define START_OFFSET_X 36 // GRID_WIDTH * 4.5
#define START_OFFSET_Y 28 // GRID_HEIGHT * 3.5
#define START_WIDTH 72 // GRID_WIDTH * 9
#define START_HEIGHT 88 // GRID_HEIGHT * 11
// Color Button placement
#define BLOCK_SPACE_X 6
#define BLOCK_SPACE_Y 6
#define BLOCK_OFFSET_X (ART_WIDTH + SIDE_BORDER + BLOCK_SPACE_X)
#define BLOCK_OFFSET_Y 74 // TOP_BORDER + 50
#define BLOCK_WIDTH 50
#define BLOCK_HEIGHT 40
#define SELECT_COLOR 0 // Always use Black for highlighting selected beacon color
#define HILITE_BORDER 4 // The highlighting frame is three pixels wide
#define XTRALITE_TRIM 42 // Color Index of lightest trim color
#define LITE_TRIM 30 // Color Index of light trim color
#define MEDIUM_TRIM 45 // Color Index of medium trim color
#define DARK_TRIM 46 // Color Index of dark trim color
// Starting value defaults
#define MAX_SWEEPS 300
#define MIN_SWEEPS 5
// Sound files
#define MID_SOUND ".\\sound\\bong.wav"
#define PICK_SOUND ".\\sound\\pick.wav"
#define LOSE_SOUND ".\\sound\\buzzer.wav"
#define WIN_SOUND ".\\SOUND\\SOUNDWON.WAV"
#define GAME_THEME ".\\sound\\beacon.mid"
#define RULES_WAV ".\\SOUND\\BEACON.WAV"
#define RULES_TEXT "BEACON.TXT"
// Backdrop bitmaps
#define MAINSCREEN ".\\ART\\BEACBRDR.BMP"
#define BEAMSCREEN ".\\ART\\BEAMS3.BMP"
// Artwork data file constants
#define DATA_FILE ".\\BEACON.DAT"
#define MAX_FILE_LENGTH 20
// New Game button area
#define NEWGAME_LOCATION_X 15
#define NEWGAME_LOCATION_Y 0
#define NEWGAME_WIDTH 217
#define NEWGAME_HEIGHT 20
/////////////////////////////////////////////////////////////////////////////
// CMainWindow:
// See game.cpp for the code to the member functions and the message map.
//
class CMainWindow : public CFrameWnd {
private:
struct BLOCK {
CRect rLocation;
unsigned int nColorIndex;
} colorBlock[NUM_BUTTONS];
void initStatics();
public:
CMainWindow();
void NewGame();
void DrawBeams(CDC *pDC);
void MoveBeam();
void CheckUnderBeam();
void SetBeamEntries(CDC *pDC);
static void DrawPart(CDC *pDC, CPoint Src, CPoint Dst, int nWidth, int nHeight);
static bool CompareColors(CDC *pDC, CPoint point);
static bool UnderLighthouse(CPoint point);
static bool InPictureSquare(CPoint point);
static CPoint PointToGrid(CPoint point);
bool LoadArtWork(CDC *pDC);
//added data members:
private:
void OnSoundNotify(CSound *pSound);
protected:
virtual bool OnCommand(WPARAM wParam, LPARAM lParam) override;
//{{AFX_MSG( CMainWindow )
afx_msg void OnPaint();
afx_msg void OnChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags);
afx_msg void OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags);
afx_msg void OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags);
afx_msg void OnTimer(uintptr nIDEvent);
afx_msg void OnLButtonDown(unsigned int nFlags, CPoint point);
afx_msg void OnLButtonUp(unsigned int nFlags, CPoint point);
afx_msg void OnMouseMove(unsigned int nFlags, CPoint point);
afx_msg void OnClose();
afx_msg LRESULT OnMCINotify(WPARAM, LPARAM);
afx_msg LRESULT OnMMIONotify(WPARAM, LPARAM);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
} // namespace Beacon
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,45 @@
/* 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 HODJNPODJ_BEACON_GLOBALS_H
#define HODJNPODJ_BEACON_GLOBALS_H
namespace Bagel {
namespace HodjNPodj {
namespace Beacon {
// Main Window positioning constants
#define GAME_WIDTH 640
#define GAME_HEIGHT 480
// Scroll button size and positioning information
#define IDC_SCROLL 850
#define SCROLL_BUTTON_X 250
#define SCROLL_BUTTON_Y 0
#define SCROLL_BUTTON_DX 140
#define SCROLL_BUTTON_DY 24
} // namespace Beacon
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,69 @@
/* 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/afxwin.h"
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
#include "bagel/hodjnpodj/beacon/beacon.h"
namespace Bagel {
namespace HodjNPodj {
namespace Beacon {
HINSTANCE hDLLInst;
HINSTANCE hExeInst;
LPGAMESTRUCT pGameInfo;
// global the pointer to the your game's main window
HWND ghParentWnd;
/////////////////////////////////////////////////////////////////////////////
// Public C interface
HWND FAR PASCAL RunBeac(HWND hParentWnd, LPGAMESTRUCT lpGameInfo) {
CMainWindow *pMain;
pGameInfo = lpGameInfo;
// invoke your game here by creating a pGame for your main window
// look at the InitInstance for your game for this
ghParentWnd = hParentWnd;
if ((pMain = new CMainWindow()) != nullptr) {
pMain->ShowWindow(SW_SHOWNORMAL);
pMain->UpdateWindow();
pMain->SetActiveWindow();
}
// these must be set in this function
hDLLInst = (HINSTANCE)GetWindowWord(pMain->m_hWnd, GWW_HINSTANCE);
hExeInst = (HINSTANCE)GetWindowWord(hParentWnd, GWW_HINSTANCE);
return pMain->m_hWnd; // return the m_hWnd of your main game window
}
} // namespace Beacon
} // namespace HodjNPodj
} // namespace Bagel

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/>.
*
*/
#ifndef HODJNPODJ_BEACON_GAMEDLL_H
#define HODJNPODJ_BEACON_GAMEDLL_H
#include "bagel/afxwin.h"
namespace Bagel {
namespace HodjNPodj {
namespace Beacon {
/**
****************************************************************
*
* RunBeac
*
* FUNCTIONAL DESCRIPTION:
*
* This is the API function for the DLL. It is what the calling app
* calls to invoke poker
*
* FORMAL PARAMETERS:
*
* hParentWnd, lpGameInfo
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************
*/
extern HWND FAR PASCAL RunBeac(HWND hParentWnd, LPGAMESTRUCT lpGameInfo);
} // namespace Beacon
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,387 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
#include "bagel/hodjnpodj/beacon/globals.h"
#include "bagel/hodjnpodj/beacon/resource.h"
#include "bagel/hodjnpodj/beacon/beacon.h"
#include "bagel/hodjnpodj/beacon/optndlg.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
namespace Bagel {
namespace HodjNPodj {
namespace Beacon {
static CPalette *pSubOptionsPalette;
static CColorButton *pOKButton = nullptr; // OKAY button on scroll
static CColorButton *pCancelButton = nullptr; // Cancel button on scroll
static CCheckButton *pAutoButton = nullptr; // Framed check box
static CCheckButton *pChangeButton = nullptr; // Framed check box
CText *m_pScoreText = nullptr;
CText *m_pSweepsText = nullptr;
CText *m_pSpeedText = nullptr;
int m_nSweepSettings[15] = {MIN_SWEEPS, 10, 15, 20, 30, 40, 50, 60, 80, 100, 120, 150, 200, 250, MAX_SWEEPS}; // 14 factors
/////////////////////////////////////////////////////////////////////////////
// COptnDlg dialog
COptnDlg::COptnDlg(CWnd* pParent, CPalette* pPalette)
: CBmpDialog(pParent, pPalette, IDD_SUBOPTIONS, ".\\ART\\SSCROLL.BMP") {
//{{AFX_DATA_INIT(COptnDlg)
m_bAutomatic = false;
m_bChangeAtTwelve = false;
m_nSweeps = 0;
m_nSpeed = MIN_SPEED;
nSweepSets = 15;
pSubOptionsPalette = pPalette;
//}}AFX_DATA_INIT
}
COptnDlg::~COptnDlg() {
if (m_pScoreText != nullptr)
delete m_pScoreText;
if (m_pSweepsText != nullptr)
delete m_pSweepsText;
if (m_pSpeedText != nullptr)
delete m_pSpeedText;
CBmpDialog::OnDestroy();
}
void COptnDlg::DoDataExchange(CDataExchange* pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COptnDlg)
DDX_Control(pDX, IDC_NUMSWEEPS, m_ScrollSweeps);
DDX_Control(pDX, IDC_SPEED, m_ScrollSpeed);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COptnDlg, CDialog)
//{{AFX_MSG_MAP(COptnDlg)
ON_WM_HSCROLL()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_BN_CLICKED(IDC_AUTOMATIC, COptnDlg::OnAutomatic)
ON_BN_CLICKED(IDC_CHANGE, COptnDlg::OnChangeAtTwelve)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COptnDlg message handlers
int COptnDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CBmpDialog::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
bool COptnDlg::OnInitDialog() {
CBmpDialog::OnInitDialog();
CDC *pDC;
CRect statRect;
int i;
pDC = GetDC();
// mSpeedTable[0] = "Leaky Rowboat";
// mSpeedTable[1] = "Kayak";
// mSpeedTable[2] = "Fishing Trawler";
mSpeedTable[0] = "Rowboat";
mSpeedTable[1] = "Dinghy";
mSpeedTable[2] = "Hovercraft";
statRect.SetRect(LEFT_SIDE, 35, LEFT_SIDE + 185, 50);
if ((m_pScoreText = new CText()) != nullptr) {
(*m_pScoreText).SetupText(pDC, pSubOptionsPalette, &statRect, JUSTIFY_LEFT);
}
statRect.SetRect(LEFT_SIDE, 20, LEFT_SIDE + 185, 35);
if ((m_pSweepsText = new CText()) != nullptr) {
(*m_pSweepsText).SetupText(pDC, pSubOptionsPalette, &statRect, JUSTIFY_LEFT);
}
m_ScrollSweeps.SetScrollRange(0, nSweepSets - 1, 0);
for (i = 0; i < (int)nSweepSets; i++) {
if (m_nSweepSettings[i] == (int)m_nSweeps)
m_ScrollSweeps.SetScrollPos(i, true);
}
statRect.SetRect(LEFT_SIDE, 70, LEFT_SIDE + 115, 88);
if ((m_pSpeedText = new CText()) != nullptr) {
(*m_pSpeedText).SetupText(pDC, pSubOptionsPalette, &statRect, JUSTIFY_LEFT);
}
m_ScrollSpeed.SetScrollRange(MIN_SPEED, MAX_SPEED, 0);
m_ScrollSpeed.SetScrollPos(m_nSpeed, true);
if ((pOKButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pOKButton).SetPalette(pSubOptionsPalette); // set the palette to use
(*pOKButton).SetControl(IDOK, this); // tie to the dialog control
}
if ((pCancelButton = new CColorButton) != nullptr) { // build a color QUIT button to let us exit
(*pCancelButton).SetPalette(pSubOptionsPalette); // set the palette to use
(*pCancelButton).SetControl(IDCANCEL, this); // tie to the dialog control
}
if ((pAutoButton = new CCheckButton) != nullptr) { // build a color QUIT button to let us exit
(*pAutoButton).SetPalette(pSubOptionsPalette); // set the palette to use
(*pAutoButton).SetControl(IDC_AUTOMATIC, this); // tie to the dialog control
}
((CWnd *)this)->CheckDlgButton(IDC_AUTOMATIC, m_bAutomatic); // Set the Auto option box
if ((pChangeButton = new CCheckButton) != nullptr) { // build a color QUIT button to let us exit
(*pChangeButton).SetPalette(pSubOptionsPalette); // set the palette to use
(*pChangeButton).SetControl(IDC_CHANGE, this); // tie to the dialog control
}
((CWnd *)this)->CheckDlgButton(IDC_CHANGE, m_bChangeAtTwelve); // Set the Auto option box
ReleaseDC(pDC);
return true; // return true unless you set the focus to a control
}
bool COptnDlg::OnEraseBkgnd(CDC *pDC) {
return true;
}
void COptnDlg::OnDestroy() {
CBmpDialog::OnDestroy();
}
bool COptnDlg::OnCommand(WPARAM wParam, LPARAM lParam) {
if (HIWORD(lParam) == BN_CLICKED) {
switch (wParam) {
case IDC_AUTOMATIC:
m_bAutomatic = !m_bAutomatic;
((CWnd *)this)->CheckDlgButton(IDC_AUTOMATIC, m_bAutomatic);
break;
case IDC_CHANGE:
m_bChangeAtTwelve = !m_bChangeAtTwelve;
((CWnd *)this)->CheckDlgButton(IDC_CHANGE, m_bChangeAtTwelve);
break;
case IDOK:
ClearDialogImage();
EndDialog(IDOK);
break;
case IDCANCEL:
ClearDialogImage();
EndDialog(0);
break;
default:
break;
} // end switch
} // end if
return true;
} // end OnCommand
void COptnDlg::OnHScroll(unsigned int nSBCode, unsigned int nPos, CScrollBar* pScrollBar) {
int pMin,
pMax;
int OldPos = pScrollBar->GetScrollPos();
int NewPos = OldPos;
pScrollBar->GetScrollRange(&pMin, &pMax);
switch (nSBCode) {
case SB_LINERIGHT:
NewPos++;
break;
case SB_PAGERIGHT:
NewPos += NUM_BUTTONS;
break;
case SB_RIGHT:
NewPos = pMax;
break;
case SB_LINELEFT:
NewPos--;
break;
case SB_PAGELEFT:
NewPos -= NUM_BUTTONS;
break;
case SB_LEFT:
NewPos = pMin;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
NewPos = nPos;
break;
}
if (NewPos < pMin) NewPos = pMin;
if (NewPos > pMax) NewPos = pMax;
if (NewPos != OldPos) { //To prevent "flicker"
(*pScrollBar).SetScrollPos(NewPos, true); //...only update when
} //...changed
UpdateScrollbars();
CDialog::OnHScroll(nSBCode, NewPos, pScrollBar);
}
/*****************************************************************
*
* UpdateScrollbars
*
* FUNCTIONAL DESCRIPTION:
*
* Updates data adjusted with scrollbars
*
* FORMAL PARAMETERS:
*
* none
*
* IMPLICIT INPUT PARAMETERS:
*
* CScrollbar pScrollTime, pScrollColumns, pScrollRows
*
* IMPLICIT OUTPUT PARAMETERS:
*
* int m_nTime, m_nNumParts, m_nColumns, m_nRows
*
* RETURN VALUE:
*
* void
*
****************************************************************/
void COptnDlg::UpdateScrollbars() {
unsigned int OldValue;
CDC *pDC;
char msg[64];
pDC = GetDC();
OldValue = m_nSweeps;
m_nSweeps = m_nSweepSettings[m_ScrollSweeps.GetScrollPos()];
if (OldValue != m_nSweeps) {
if (m_nSweeps == MAX_SWEEPS)
Common::sprintf_s(msg, "Number of Sweeps: Unlimited");
else
Common::sprintf_s(msg, "Number of Sweeps: %d", m_nSweeps);
(*m_pSweepsText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
}
OldValue = m_nSpeed;
m_nSpeed = m_ScrollSpeed.GetScrollPos();
if (OldValue != m_nSpeed) {
Common::sprintf_s(msg, "Speed: %s", mSpeedTable[m_nSpeed].c_str());
(*m_pSpeedText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
}
ReleaseDC(pDC);
}
void COptnDlg::OnAutomatic() {
m_bAutomatic = !m_bAutomatic;
((CWnd *)this)->CheckDlgButton(IDC_AUTOMATIC, m_bAutomatic);
}
void COptnDlg::OnChangeAtTwelve() {
m_bChangeAtTwelve = !m_bChangeAtTwelve;
((CWnd *)this)->CheckDlgButton(IDC_CHANGE, m_bChangeAtTwelve);
}
void COptnDlg::OnOK() {
ClearDialogImage();
EndDialog(IDOK);
}
void COptnDlg::OnCancel() {
ClearDialogImage();
EndDialog(0);
}
void COptnDlg::OnPaint() {
CDC *pDC;
char msg[64];
CBmpDialog::OnPaint();
pDC = GetDC();
Common::sprintf_s(msg, "(Effective on New Game)");
(*m_pScoreText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
if (m_nSweeps == MAX_SWEEPS)
Common::sprintf_s(msg, "Number of Sweeps: Unlimited");
else
Common::sprintf_s(msg, "Number of Sweeps: %d", m_nSweeps);
(*m_pSweepsText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
Common::sprintf_s(msg, "Speed: %s", mSpeedTable[m_nSpeed].c_str());
(*m_pSpeedText).DisplayString(pDC, msg, 14, FW_BOLD, OPTIONS_COLOR);
ReleaseDC(pDC);
}
void COptnDlg::ClearDialogImage() {
if (pOKButton != nullptr) { // release the button
delete pOKButton;
pOKButton = nullptr;
}
if (pCancelButton != nullptr) { // release the button
delete pCancelButton;
pCancelButton = nullptr;
}
if (pAutoButton != nullptr) { // release the button
delete pAutoButton;
pAutoButton = nullptr;
}
if (pChangeButton != nullptr) { // release the button
delete pChangeButton;
pChangeButton = nullptr;
}
ValidateRect(nullptr);
}
} // namespace Beacon
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,86 @@
/* 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 HODJNPODJ_BEACON_OPTNDLG_H
#define HODJNPODJ_BEACON_OPTNDLG_H
#include "bagel/hodjnpodj/beacon/resource.h"
#include "bagel/hodjnpodj/hnplibs/cbofdlg.h"
#include "bagel/hodjnpodj/hnplibs/text.h"
namespace Bagel {
namespace HodjNPodj {
namespace Beacon {
#define LEFT_SIDE 30
#define OPTIONS_COLOR RGB(0, 0, 0) // Color of the stats info CText
#define NUM_SPEEDS 3
/////////////////////////////////////////////////////////////////////////////
// COptnDlg dialog
class COptnDlg : public CBmpDialog {
// Construction
public:
COptnDlg(CWnd* pParent = nullptr, CPalette *pPalette = nullptr); // standard constructor
~COptnDlg(); // destructor
void UpdateScrollbars();
void ClearDialogImage();
// Dialog Data
//{{AFX_DATA(COptnDlg)
enum { IDD = IDD_SUBOPTIONS };
CScrollBar m_ScrollSweeps;
CScrollBar m_ScrollSpeed;
bool m_bAutomatic = false;
bool m_bChangeAtTwelve = false;
unsigned int m_nSweeps = 0;
unsigned int m_nSpeed = 0;
unsigned int nSweepSets = 0;
CString mSpeedTable [NUM_SPEEDS];
//}}AFX_DATA
// Implementation
protected:
virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support
// Generated message map functions
//{{AFX_MSG(COptnDlg)
virtual bool OnCommand(WPARAM wParam, LPARAM lParam) override;
virtual bool OnInitDialog() override;
afx_msg void OnHScroll(unsigned int nSBCode, unsigned int nPos, CScrollBar* pScrollBar);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg bool OnEraseBkgnd(CDC *pDC);
virtual void OnOK() override;
virtual void OnCancel() override;
afx_msg void OnPaint();
afx_msg void OnAutomatic();
afx_msg void OnChangeAtTwelve();
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
} // namespace Beacon
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,45 @@
/* 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 HODJNPODJ_BATTLEFISH_USERCFG_H
#define HODJNPODJ_BATTLEFISH_USERCFG_H
namespace Bagel {
namespace HodjNPodj {
namespace Battlefish {
#define IDD_SUBOPTIONS 115
#define IDB_BEACON_BMP 301
#define IDC_RULES 1002
#define IDC_NUMSWEEPS 1021
#define IDC_SPEED 1023
#define IDC_CHANGE 1024
#define IDC_AUTOMATIC 1025
} // namespace Beacon
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,78 @@
/* 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/hodjnpodj/console.h"
#include "bagel/hodjnpodj/hodjnpodj.h"
#include "bagel/afxwin.h"
namespace Bagel {
namespace HodjNPodj {
Console::Console() : GUI::Debugger() {
registerCmd("dumpres", WRAP_METHOD(Console, cmdDumpRes));
}
Console::~Console() {
}
bool Console::cmdDumpRes(int argc, const char **argv) {
if (argc == 2) {
int num = atoi(argv[1]);
Common::String name = Common::String::format("#%d", num);
HINSTANCE hInst = nullptr;
uint dwBytes;
HRSRC hRsc;
HGLOBAL hGbl;
byte *pData;
hRsc = FindResource(hInst, name.c_str(), RT_BITMAP);
if (hRsc != nullptr) {
dwBytes = (size_t)SizeofResource(hInst, hRsc);
hGbl = LoadResource(hInst, hRsc);
if ((dwBytes != 0) && (hGbl != nullptr)) {
pData = (byte *)LockResource(hGbl);
Common::MemoryReadStream rs(pData, dwBytes);
Common::DumpFile df;
if (df.open("dump.bin"))
df.writeStream(&rs);
UnlockResource(hGbl);
FreeResource(hGbl);
if (df.isOpen())
debugPrintf("Created dump.bin\n");
else
debugPrintf("Could not create dump.bin\n");
} else {
debugPrintf("Could not find resource\n");
}
} else {
debugPrintf("Could not find resource\n");
}
} else {
debugPrintf("dumpres [num]\n");
}
return true;
}
} // namespace HodjNPodj
} // namespace Bagel

View File

@@ -0,0 +1,43 @@
/* 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 HODJNPODJ_CONSOLE_H
#define HODJNPODJ_CONSOLE_H
#include "gui/debugger.h"
namespace Bagel {
namespace HodjNPodj {
class Console : public GUI::Debugger {
private:
bool cmdDumpRes(int argc, const char **argv);
public:
Console();
~Console() override;
};
} // namespace HodjNPodj
} // namespace Bagel
#endif

View File

@@ -0,0 +1,791 @@
/* 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/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/sprite.h"
#include "bagel/hodjnpodj/crypt/globals.h"
#include "bagel/hodjnpodj/crypt/crypt.h"
#include "bagel/hodjnpodj/hodjnpodj.h"
#include "bagel/metaengine.h"
namespace Bagel {
namespace HodjNPodj {
namespace Crypt {
/*****************************************************************
*
* CCryptogram
*
* FUNCTIONAL DESCRIPTION:
*
* Initializes members.
*
* FORMAL PARAMETERS:
*
* None
*
* IMPLICIT INPUT PARAMETERS:
*
* None
*
* IMPLICIT OUTPUT PARAMETERS:
*
* None
*
* RETURN VALUE:
*
* None
*
****************************************************************/
CCryptogram::CCryptogram(CDC *pDC) {
m_cRecordGram = new CCryptRecord();
m_cPaintGram = new CPaintGram(pDC);
m_cStats = new CStats();
/********************************************************
* Solved switch is used to prevent further user updates *
* after cryptogram is solved. *
********************************************************/
bIsGameOver = false; // Initialize solved switch
BagelMetaEngine::setKeybindingMode(KBMODE_MINIMAL);
}
/*****************************************************************
*
* ~Cryptogram
*
* FUNCTIONAL DESCRIPTION:
*
* Destructor
*
* FORMAL PARAMETERS:
*
* n/a
*
* IMPLICIT INPUT PARAMETERS:
*
* n/a
*
* IMPLICIT OUTPUT PARAMETERS:
*
* n/a
*
* RETURN VALUE:
*
* n/a
*
****************************************************************/
CCryptogram::~CCryptogram() {
if (m_cStats != nullptr)
delete m_cStats;
if (m_cPaintGram != nullptr)
delete m_cPaintGram;
if (m_cRecordGram != nullptr)
delete m_cRecordGram;
BagelMetaEngine::setKeybindingMode(KBMODE_NORMAL);
}
/*****************************************************************
*
* DrawGram
*
* FUNCTIONAL DESCRIPTION:
*
* [Description of function]
*
* FORMAL PARAMETERS:
*
* [Show arguments]
*
* IMPLICIT INPUT PARAMETERS:
*
* [External data read]
*
* IMPLICIT OUTPUT PARAMETERS:
*
* [External data modified]
*
* RETURN VALUE:
*
* [Discuss return value]
*
****************************************************************/
bool CCryptogram::DrawGram(CDC *pDC) {
bIsGameOver = false;
if (m_cRecordGram->GetRecord(m_cStats->ResetGame()) == false) // Attempt to get the record
return false;
m_cPaintGram->ClearGram(pDC);
m_cPaintGram->PaintAlphabet(pDC);
CreateCryptMap(m_cStats->m_nLettersSolved);
MarkSolvedLetters(pDC);
m_cPaintGram->InitGramPosition(m_cRecordGram);
m_cPaintGram->PaintGram(pDC, m_chEncryptGram);
return true;
}
void CCryptogram::DrawSource(CDC *pDC) {
m_cPaintGram->HiLiteOff(pDC);
m_cPaintGram->PaintGram(pDC, m_cRecordGram->GetSource());
}
void CCryptogram::MarkSolvedLetters(CDC *pDC) {
int i;
for (i = 0; i < ALPHABET; i++) { // flip thru Crypt Map
if (m_nCryptMap[DECRYPT_MAP][i] == i) // Does letter rep itself?
m_cPaintGram->RevealOn( // yes - Mark char as solved
pDC,
m_cPaintGram->IndexToChar(i)
);
} // end for
}
void CCryptogram::SolveCryptogram(CDC *pDC) {
int nReplaceCode;
int nAlphaCode;
int nGramCode;
int i;
for (i = 0; i < ALPHABET; i++) { // flip thru Crypt Map
if ((m_nCryptMap[DECRYPT_MAP][i] != i) && // Any chars rep another char?
(m_nCryptMap[DECRYPT_MAP][i] != NOT_USED)) {
nAlphaCode = m_cPaintGram->IndexToChar(i); // Replace this char
nGramCode = m_cPaintGram->IndexToChar(m_nCryptMap[DECRYPT_MAP][i]);
nReplaceCode = UpdateCryptMap(nGramCode, nAlphaCode); // Update internal rep
if (nReplaceCode != NOT_USED) { // New char used in gram?
m_cPaintGram->ReplaceLetter(pDC, m_cPaintGram->GetCharType(nAlphaCode), // Yes - swap w/temp char
m_cPaintGram->SetLimboTypeOn(nReplaceCode)); // ...Temporarily set it's code to limbo
m_cPaintGram->ReplaceLetter(pDC, nGramCode, m_cPaintGram->GetCharType(nAlphaCode)); // swap old char with new char
m_cPaintGram->ReplaceLetter(pDC, m_cPaintGram->SetLimboTypeOn(nReplaceCode), // Turn all limbo types off
m_cPaintGram->SetLimboTypeOff(nReplaceCode));
} else { // New char was not used in gram...
m_cPaintGram->ReplaceLetter(pDC, nGramCode, m_cPaintGram->GetCharType(nAlphaCode)); // ...simply replace old with new.
}
m_cPaintGram->UsedOff(pDC, nGramCode); // Turn used code off on old char since it's not being used anymore
m_cPaintGram->UsedOn(pDC, nAlphaCode); // Turn used code on new char now appearing in cryptogram
} // end if
} // end for
}
/*****************************************************************
*
* HandleUserUpdate
*
* FUNCTIONAL DESCRIPTION:
*
* Processes user interaction with the displayed cryptogram.
* Will modify both internal cryptogram representation by calling
* appropriate CCryptogram members, and visual crytogram rep by
* calling CPaintGram members.
*
* FORMAL PARAMETERS:
*
* pDC - used for visual updating
* cpointClicked - place where user clicked
*
* IMPLICIT INPUT PARAMETERS:
*
* m_cPaintGram member
*
* IMPLICIT OUTPUT PARAMETERS:
*
* modifies m_cPaintGram
*
* RETURN VALUE:
*
* void
*
****************************************************************/
bool CCryptogram::HandleUserUpdate(CDC *pDC, CPoint cpointClicked) {
CSprite *pSprite;
int nClickedCode;
int nHiLiteCode;
int nReplaceCode;
int nAlphaCode;
int nGramCode;
/*****************************
* Cryptogram already solved? *
*****************************/
if (bIsGameOver == true) {
//MessageBeep(-1); // No - exit
return false;
}
pSprite = m_cPaintGram->m_cDisplayLetters->Touched(cpointClicked);
/********************************
* Clicked on letter anywhere? *
********************************/
if (pSprite == nullptr) {
//MessageBeep(-1); // No - exit
return false;
}
/********************
* Symbol hilited? *
********************/
nClickedCode = (*pSprite).GetTypeCode();
if (m_cPaintGram->IsSymbolChar(nClickedCode) == true) {
return false; // Yes - do not hilite symbols
}
/********************
* Anything hilited? *
********************/
if (m_cPaintGram->IsHiLiteOn() == false) {
m_cPaintGram->HiLiteOn(pDC, nClickedCode); // No - hilite letter
return false;
}
/****************************************************************
* Was the letter clicked same as the letter currenly hilited? *
****************************************************************/
if (m_cPaintGram->IsHiLiteType(nClickedCode) == true) {
m_cPaintGram->HiLiteOff(pDC); // Yes - toggle hilite to off state
return false;
}
/************************************************************
* Was the area clicked same as the area currenly hilited? *
************************************************************/
nHiLiteCode = m_cPaintGram->GetHiLiteType(pDC);
ASSERT(nHiLiteCode);
if (
(m_cPaintGram->IsGramType(nClickedCode) &&
m_cPaintGram->IsGramType(nHiLiteCode)) ||
(m_cPaintGram->IsAlphabetType(nClickedCode) &&
m_cPaintGram->IsAlphabetType(nHiLiteCode))
) {
m_cPaintGram->HiLiteOff(pDC); // Yes - turn hilite off
m_cPaintGram->HiLiteOn(pDC, nClickedCode); // ...hilite new char
return false; // out of here.
}
/************************************************************
* User wants to switch letters. *
* Need to update internal cryptogram and visual reps. *
************************************************************/
if (m_cPaintGram->IsAlphabetType(nHiLiteCode) == true) { // Is the hilited char in the alphabet region?
nAlphaCode = nHiLiteCode; // Yes - assign it the alpha code
nGramCode = nClickedCode;
} else {
nAlphaCode = nClickedCode; // No - swap around clicked code
nGramCode = nHiLiteCode;
}
nReplaceCode = UpdateCryptMap(nGramCode, nAlphaCode); // Update internal rep
if (nReplaceCode != NOT_USED) { // New char used in gram?
/****************************************************************
* These next lines introduces the "LimboType." From the fact *
* that the new letter, "nAlphaCode," is already somewhere in *
* the displayed cryptogram, two additional letters need *
* replacing -- not just the old letter, "nGramCode," with the *
* new. The following algorithm was used to resolve this: *
* - The new char currently displayed needs to be replaced *
* with another temp char, "nReplaced," which is the *
* old char + LimboType. *
* - Next all old chars are replaced with the new char. Note *
* that the "old char + LimboType" will not be replaced with *
* the new char. *
* - Finally, set back temp char, "old + limbo," with old *
* char. *
* *
* That's what the next three lines do respectively. *
****************************************************************/
m_cPaintGram->ReplaceLetter(pDC, m_cPaintGram->GetCharType(nAlphaCode), // Yes - swap w/temp char
m_cPaintGram->SetLimboTypeOn(nReplaceCode)); // ...Temporarily set it's code to limbo
m_cPaintGram->ReplaceLetter(pDC, nGramCode, m_cPaintGram->GetCharType(nAlphaCode)); // swap old char with new char
m_cPaintGram->ReplaceLetter(pDC, m_cPaintGram->SetLimboTypeOn(nReplaceCode), // Turn all limbo types off
m_cPaintGram->SetLimboTypeOff(nReplaceCode));
} else { // New char was not used in gram...
m_cPaintGram->ReplaceLetter(pDC, nGramCode, m_cPaintGram->GetCharType(nAlphaCode)); // ...simply replace old with new.
}
m_cPaintGram->HiLiteOff(pDC); // Turn hilite off
m_cPaintGram->UsedOff(pDC, nGramCode); // Turn used code off on old char since it's not being used anymore
m_cPaintGram->UsedOn(pDC, nAlphaCode); // Turn used code on new char now appearing in cryptogram
return IsSolved();
}
/*****************************************************************
*
* HandleUserUpdate
*
* FUNCTIONAL DESCRIPTION:
*
* Processes user interaction with the displayed cryptogram.
* Will modify both internal cryptogram representation by calling
* appropriate CCryptogram members, and visual crytogram rep by
* calling CPaintGram members.
*
* FORMAL PARAMETERS:
*
* pDC - used for visual updating
* cpointClicked - place where user clicked
*
* IMPLICIT INPUT PARAMETERS:
*
* m_cPaintGram member
*
* IMPLICIT OUTPUT PARAMETERS:
*
* modifies m_cPaintGram
*
* RETURN VALUE:
*
* void
*
****************************************************************/
bool CCryptogram::HandleUserUpdate(CDC *pDC, unsigned int nChar) {
char nNewChar = toupper(nChar);
int nHiLiteCode;
int nReplaceCode;
int nAlphaCode;
int nGramCode;
/*****************************
* Cryptogram already solved? *
*****************************/
if (bIsGameOver == true) {
//MessageBeep(-1); // No - exit
return false;
}
/****************************************
* Is this a valid alphabetical letter? *
****************************************/
if (Common::isAlpha(nNewChar) == false) {
MessageBeep(-1); // No - exit
return false;
}
/********************
* Anything hilited? *
********************/
if (m_cPaintGram->IsHiLiteOn() == false) {
m_cPaintGram->HiLiteOn(pDC, nNewChar); // Turn hilite on that spec char
return false;
}
/*******************************
* Hilite in cryptogram region? *
*******************************/
nHiLiteCode = m_cPaintGram->GetHiLiteType(pDC);
ASSERT(nHiLiteCode);
if (m_cPaintGram->IsGramType(nHiLiteCode) == false) {
MessageBeep(-1); // No - exit
return false;
}
/*************************************
* Hilite same char as user typed in? *
*************************************/
if (nHiLiteCode == nNewChar) {
m_cPaintGram->HiLiteOff(pDC); // Turn hilite off
return false;
}
nAlphaCode = nNewChar;
nGramCode = nHiLiteCode;
/************************************************************
* User wants to switch letters. *
* Need to update internal cryptogram and visual reps. *
************************************************************/
nReplaceCode = UpdateCryptMap(nGramCode, nAlphaCode); // Update internal rep
if (nReplaceCode != NOT_USED) { // New char used in gram?
/****************************************************************
* These next lines introduces the "LimboType." From the fact *
* that the new letter, "nAlphaCode," is already somewhere in *
* the displayed cryptogram, two additional letters need *
* replacing -- not just the old letter, "nGramCode," with the *
* new. The following algorithm was used to resolve this: *
* - The new char currently displayed needs to be replaced *
* with another temp char, "nReplaced," which is the *
* old char + LimboType. *
* - Next all old chars are replaced with the new char. Note *
* that the "old char + LimboType" will not be replaced with *
* the new char. *
* - Finally, set back temp char, "old + limbo," with old *
* char. *
* *
* That's what the next three lines do respectively. *
****************************************************************/
m_cPaintGram->ReplaceLetter(pDC, m_cPaintGram->GetCharType(nAlphaCode), // Yes - swap w/temp char
m_cPaintGram->SetLimboTypeOn(nReplaceCode)); // ...Temporarily set it's code to limbo
m_cPaintGram->ReplaceLetter(pDC, nGramCode, m_cPaintGram->GetCharType(nAlphaCode)); // swap old char with new char
m_cPaintGram->ReplaceLetter(pDC, m_cPaintGram->SetLimboTypeOn(nReplaceCode), // Turn all limbo types off
m_cPaintGram->SetLimboTypeOff(nReplaceCode));
} else { // New char was not used in gram...
m_cPaintGram->ReplaceLetter(pDC, nGramCode, m_cPaintGram->GetCharType(nAlphaCode)); // ...simply replace old with new.
}
m_cPaintGram->HiLiteOff(pDC); // Turn hilite off
m_cPaintGram->UsedOff(pDC, nGramCode); // Turn used code off on old char since it's not being used anymore
m_cPaintGram->UsedOn(pDC, nAlphaCode); // Turn used code on new char now appearing in cryptogram
return IsSolved();
}
/*****************************************************************
*
* Encrypt
*
* FUNCTIONAL DESCRIPTION:
*
* Uses the Crypt Map to encode the phrase, as it originally
* appears.
*
* FORMAL PARAMETERS:
*
* None
*
* IMPLICIT INPUT PARAMETERS:
*
* m_cRecordGram - to obtain the original phrase.
* m_nCryptMap - to encrypt phrase
*
* IMPLICIT OUTPUT PARAMETERS:
*
* m_chEncrptGram - updated according to structure of
* m_nCryptMap.
*
* RETURN VALUE:
*
* void
*
****************************************************************/
void CCryptogram::Encrypt() {
int i;
/*******************
* Reset workbench. *
*******************/
Common::strcpy_s(m_chEncryptGram, m_cRecordGram->GetGram()); // Acquire copy of original
/*****************************************
* Encrypt entire string using crypt map. *
*****************************************/
for (i = 0; m_chEncryptGram[i] != 0; i++) {
if ((m_cPaintGram->IsAlphaChar(m_chEncryptGram[i]) == true) && // Is this a char?
(m_nCryptMap[DECRYPT_MAP][m_cPaintGram->CharToIndex(m_chEncryptGram[i])] != NOT_USED) // and should this char be encrypted?
) {
m_chEncryptGram[i] = m_cPaintGram->IndexToChar(
m_nCryptMap[DECRYPT_MAP][
m_cPaintGram->CharToIndex(m_chEncryptGram[i])
]
);
}
}
}
/*****************************************************************
*
* CreateEncryptMap
*
* FUNCTIONAL DESCRIPTION:
*
* Creates an En-Cryption Map Key by randomally selecting
* unique representations for each alphabetical letter.
*
* FORMAL PARAMETERS:
*
* nLettersSolved - number of characters not encrypted
*
* IMPLICIT INPUT PARAMETERS:
*
* m_nCryptMap - Resets En-Cryption Map Key
*
* IMPLICIT OUTPUT PARAMETERS:
*
* m_nCryptMap - Complete En-Cryption Map Key with exactly
* nLettersSolved chars mapped to themselves.
*
* RETURN VALUE:
*
* void
*
****************************************************************/
void CCryptogram::CreateCryptMap(int nLettersSolved) {
int nEncryptCode; // encrypted value
int nDecryptCode; // normal/decrypted value
bool bIsUsed; // tells if encrypt-decrypt map was used
int i, j; // index
/*******************
* Reset workbench. *
*******************/
Common::strcpy_s(m_chEncryptGram, m_cRecordGram->GetGram()); // Acquire copy of original
for (i = 0; i < ALPHABET; i++) { // Reset cryptmap
m_nCryptMap[DECRYPT_MAP][i] = NOT_USED;
m_nCryptMap[ENCRYPT_MAP][i] = NOT_USED;
}
/****************************************************
* Create encryption map based on letters in phrase. *
****************************************************/
for (i = 0; m_chEncryptGram[i] != 0; i++) {
if (m_cPaintGram->IsAlphaChar(m_chEncryptGram[i]) == true) { // Is this a char?
nDecryptCode = m_cPaintGram->CharToIndex(m_chEncryptGram[i]);
bIsUsed = (m_nCryptMap[DECRYPT_MAP][nDecryptCode] != NOT_USED);
if (bIsUsed == true) // Char already encrypted?
continue; // Yes - loop to next char in text
/******************************
* Find an unused encrypt map. *
******************************/
do {
nEncryptCode = brand() % ALPHABET;
bIsUsed = (m_nCryptMap[ENCRYPT_MAP][nEncryptCode] != NOT_USED);
} while (bIsUsed == true || nEncryptCode == nDecryptCode); // find unused map
/**************************************
* Record new encrypt/decrypt mapping. *
**************************************/
m_nCryptMap[DECRYPT_MAP][nDecryptCode] = nEncryptCode;
m_nCryptMap[ENCRYPT_MAP][nEncryptCode] = nDecryptCode;
}
}
/************************************************************************
* Decrypt letters solved given as function arg. *
* To keep letters solved random (as opposed to decrypting A, B, and C *
* in order) it seemed easier to change the map after it was fully *
* encrypted, provided from above. *
************************************************************************/
for (i = 0; i < nLettersSolved ; i++) {
for (j = 0; j < ALPHABET; j++) { // Are there any letters left to decrypt?
if (
m_nCryptMap[DECRYPT_MAP][j] != NOT_USED && // in the quote and
m_nCryptMap[DECRYPT_MAP][j] != j // not already solved
) {
bIsUsed = true; // Yes - so break
break;
} else
bIsUsed = false; // No - not this letter, keep looking
}
if (bIsUsed == false) // Any letters left to decrypt?
break; // No - by pass loop.
do {
nDecryptCode = brand() % ALPHABET; // find used char
bIsUsed = (
m_nCryptMap[DECRYPT_MAP][nDecryptCode] != NOT_USED && // in quote and
m_nCryptMap[DECRYPT_MAP][nDecryptCode] != nDecryptCode // not already solved
);
} while (bIsUsed == false);
nEncryptCode = m_nCryptMap[DECRYPT_MAP][nDecryptCode]; // gets corres decoder
/********************************************************************
* Need to know if the decrypted letter was used in the encryption *
* map before. If it was, then another encryption letter needs to *
* be used in it's place. *
********************************************************************/
bIsUsed = (m_nCryptMap[ENCRYPT_MAP][nDecryptCode] != NOT_USED);
if (bIsUsed == true) { // Decrypted letter used before?
m_nCryptMap[DECRYPT_MAP][m_nCryptMap[ENCRYPT_MAP][nDecryptCode]] = nEncryptCode; // Yes - Swap around encrypted chars
m_nCryptMap[ENCRYPT_MAP][nEncryptCode] = m_nCryptMap[ENCRYPT_MAP][nDecryptCode];
} else {
m_nCryptMap[ENCRYPT_MAP][nEncryptCode] = NOT_USED; // No - Mark encryption map as unused
}
/********************************************************************
* ENCRYPT_MAP is a reversed mirror of DECRYPT_MAP. I.e. if *
* "A points to X" in the DECRYPT_MAP, then "X points to A" in the *
* ENCRYPT_MAP. Specific reasons for assigning both sides of map *
* to "nDecryptCode" are tricky...8-]. Think about it. *
********************************************************************/
m_nCryptMap[DECRYPT_MAP][nDecryptCode] = nDecryptCode; // Match Decrypt map
m_nCryptMap[ENCRYPT_MAP][nDecryptCode] = nDecryptCode; // ...with Encrypt map
}
Encrypt(); // Create the real thing...update internal rep.
}
/*****************************************************************
*
* UpdateGramChar
*
* FUNCTIONAL DESCRIPTION:
*
* Replaces old char, "nOldType," with new char, "nNewType," in
* Crypt Map. Handles specific case when new char appears in
* Crypt Map prior to replacement.
*
* FORMAL PARAMETERS:
*
* nOldType - type code of old char
* nNewType - type code of new char
*
* IMPLICIT INPUT PARAMETERS:
*
* m_nCryptMap - En-Cryption Map Key
*
* IMPLICIT OUTPUT PARAMETERS:
*
* m_nCryptMap - nOldType is remapped to nNewType
*
* RETURN VALUE:
*
* nReplaceCode - value of any additional character that may
* need replacing.
*
****************************************************************/
int CCryptogram::UpdateCryptMap(int nOldType, int nNewType) {
int nOldIndex; // Crypt Map index equivalent of nOldType
int nNewIndex; // index equivalent of nNewType
int nEncryptCode; // old type
int nDecryptCode; // decryption map corresponding to old type
int nReplaceCode; // temporary old type
nOldIndex = m_cPaintGram->CharToIndex(m_cPaintGram->GetCharType(nOldType));
nNewIndex = m_cPaintGram->CharToIndex(m_cPaintGram->GetCharType(nNewType));
nEncryptCode = nOldIndex;
nDecryptCode = m_nCryptMap[ENCRYPT_MAP][nEncryptCode];
nReplaceCode = NOT_USED;
/************************************************************************
* Need to know if nNewType letter was used in the cryptogram *
* before. This can occur in two different instances: another letter *
* was encrypted into nNewType, or when nNewType just appears as a *
* straight representation of itself. If either was case, then another *
* letter needs to be used in it's place. *
************************************************************************/
if (m_nCryptMap[ENCRYPT_MAP][nNewIndex] != NOT_USED) { // New type used in encryption ma?
m_nCryptMap[DECRYPT_MAP][m_nCryptMap[ENCRYPT_MAP][nNewIndex]] = nEncryptCode; // Swap around encrypted chars
m_nCryptMap[ENCRYPT_MAP][nEncryptCode] = m_nCryptMap[ENCRYPT_MAP][nNewIndex];
nReplaceCode = m_cPaintGram->IndexToChar(nEncryptCode);
} else {
m_nCryptMap[ENCRYPT_MAP][nEncryptCode] = NOT_USED;
}
m_nCryptMap[DECRYPT_MAP][nDecryptCode] = nNewIndex; // Match Decrypt map
m_nCryptMap[ENCRYPT_MAP][nNewIndex] = nDecryptCode; // ...with Encrypt map
Encrypt(); // Update internal rep
return nReplaceCode; // return temporary value....
}
/*****************************************************************
*
* IsSolved
*
* FUNCTIONAL DESCRIPTION:
*
* Figures out if the cryptogram is solved, based on
* state of "m_nCryptMap" -- the En-Cryption Map Key.
*
* FORMAL PARAMETERS:
*
* void
*
* IMPLICIT INPUT PARAMETERS:
*
* m_nCryptMap - En-Cryption Map Key
*
* IMPLICIT OUTPUT PARAMETERS:
*
* None
*
* RETURN VALUE:
*
* nTotalSolved - number of correctly decrypted letters
*
****************************************************************/
bool CCryptogram::IsSolved() {
int i;
for (i = 0; i < ALPHABET; i++) { // flip thru Crypt Map
if ((m_nCryptMap[DECRYPT_MAP][i] != i) && // Any chars rep another char?
(m_nCryptMap[DECRYPT_MAP][i] != NOT_USED))
return false; // Yes - cryptogram not solved
}
bIsGameOver = true; // Mark cryptogram as solved
return true;
}
/*****************************************************************
*
* LettersSolved
*
* FUNCTIONAL DESCRIPTION:
*
* Figures out how many letters are properly decrypted, based on
* state of "m_nCryptMap" -- the En-Cryption Map Key.
*
* FORMAL PARAMETERS:
*
* void
*
* IMPLICIT INPUT PARAMETERS:
*
* m_nCryptMap - En-Cryption Map Key
*
* IMPLICIT OUTPUT PARAMETERS:
*
* None
*
* RETURN VALUE:
*
* nTotalSolved - number of correctly decrypted letters
*
****************************************************************/
int CCryptogram::LettersSolved() {
int i;
int nTotalSolved = 0;
for (i = 0; i < ALPHABET; i++) { // flip thru Crypt Map
if (m_nCryptMap[DECRYPT_MAP][i] == i) // Does letter rep itself?
nTotalSolved++; // Yes - it is a solved letter
}
return nTotalSolved;
}
} // namespace Crypt
} // namespace HodjNPodj
} // 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 HODJNPODJ_CRYPT_CRYPT_H
#define HODJNPODJ_CRYPT_CRYPT_H
#include "bagel/hodjnpodj/crypt/rec.h"
#include "bagel/hodjnpodj/crypt/pnt_gram.h"
#include "bagel/hodjnpodj/crypt/stats.h"
namespace Bagel {
namespace HodjNPodj {
namespace Crypt {
#define SPLASHSPEC ".\\art\\crypt.BMP" // bitmap file for the splash screen
#define NOT_USED -1
#define MAP 2
#define DECRYPT_MAP 0
#define ENCRYPT_MAP 1
class CCryptogram {
private:
CCryptRecord *m_cRecordGram = nullptr;
int m_nCryptMap[MAP][ALPHABET] = {};
public:
CCryptogram(CDC *pDC);
~CCryptogram();
bool DrawGram(CDC *pDC);
bool HandleUserUpdate(CDC *pDC, CPoint cpointClicked);
bool HandleUserUpdate(CDC *pDC, unsigned int nChar);
void Encrypt();
void CreateCryptMap(int nLettersSolved);
int UpdateCryptMap(int nOldType, int nNewType);
bool IsSolved();
int LettersSolved();
void MarkSolvedLetters(CDC *pDC);
void SolveCryptogram(CDC *pDC);
void DrawSource(CDC *pDC);
char m_chEncryptGram[MAX_GRAM_LEN];
CPaintGram *m_cPaintGram = nullptr;
CStats *m_cStats = nullptr;
bool bIsGameOver = false;
};
// Globals!
extern CPalette *pGamePalette;
} // namespace Crypt
} // namespace HodjNPodj
} // namespace Bagel
#endif

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