Initial commit
This commit is contained in:
2
engines/hopkins/POTFILES
Normal file
2
engines/hopkins/POTFILES
Normal file
@@ -0,0 +1,2 @@
|
||||
engines/hopkins/metaengine.cpp
|
||||
|
||||
796
engines/hopkins/anim.cpp
Normal file
796
engines/hopkins/anim.cpp
Normal file
@@ -0,0 +1,796 @@
|
||||
/* 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 "hopkins/anim.h"
|
||||
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/graphics.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/file.h"
|
||||
#include "common/rect.h"
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
AnimationManager::AnimationManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
_clearAnimationFl = false;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
Common::fill((byte *)&Bank[i], (byte *)&Bank[i] + sizeof(BankItem), 0);
|
||||
for (int i = 0; i < 35; ++i)
|
||||
Common::fill((byte *)&_animBqe[i], (byte *)&_animBqe[i] + sizeof(BqeAnimItem), 0);
|
||||
}
|
||||
|
||||
void AnimationManager::clearAll() {
|
||||
initAnimBqe();
|
||||
}
|
||||
|
||||
/**
|
||||
* Play Animation
|
||||
* @param filename Filename of animation to play
|
||||
* @param rate1 Delay amount before starting animation
|
||||
* @param rate2 Delay amount between animation frames
|
||||
* @param rate3 Delay amount after animation finishes
|
||||
*/
|
||||
void AnimationManager::playAnim(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) {
|
||||
Common::File f;
|
||||
|
||||
if (_vm->shouldQuit())
|
||||
return;
|
||||
|
||||
_vm->_events->mouseOff();
|
||||
|
||||
byte *screenP = _vm->_graphicsMan->_backBuffer;
|
||||
|
||||
if (!f.open(hiresName)) {
|
||||
if (!f.open(lowresName))
|
||||
error("Files not found: %s - %s", hiresName.toString().c_str(), lowresName.toString().c_str());
|
||||
}
|
||||
|
||||
f.skip(6);
|
||||
f.read(_vm->_graphicsMan->_palette, 800);
|
||||
f.skip(4);
|
||||
size_t nbytes = f.readUint32LE();
|
||||
f.skip(14);
|
||||
f.read(screenP, nbytes);
|
||||
|
||||
if (_clearAnimationFl)
|
||||
_vm->_graphicsMan->clearScreen();
|
||||
|
||||
if (skipSeqFl) {
|
||||
_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
|
||||
} else {
|
||||
_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
|
||||
_vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
}
|
||||
_vm->_events->_rateCounter = 0;
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_vm->_soundMan->loadAnimSound();
|
||||
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
// Do pre-animation delay
|
||||
do {
|
||||
if (_vm->_events->_escKeyFl)
|
||||
break;
|
||||
|
||||
_vm->_events->refreshEvents();
|
||||
} while (!_vm->shouldQuit() && _vm->_events->_rateCounter < rate1);
|
||||
}
|
||||
|
||||
if (!_vm->_events->_escKeyFl) {
|
||||
_vm->_events->_rateCounter = 0;
|
||||
int frameNumber = 0;
|
||||
while (!_vm->shouldQuit()) {
|
||||
++frameNumber;
|
||||
_vm->_soundMan->playAnimSound(frameNumber);
|
||||
|
||||
byte imageStr[17];
|
||||
// Read frame header
|
||||
if (f.read(imageStr, 16) != 16)
|
||||
break;
|
||||
imageStr[16] = 0;
|
||||
if (strncmp((const char *)imageStr, "IMAGE=", 6))
|
||||
break;
|
||||
|
||||
f.read(screenP, READ_LE_UINT32(imageStr + 8));
|
||||
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
do {
|
||||
if (_vm->_events->_escKeyFl)
|
||||
break;
|
||||
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
} while (!_vm->shouldQuit() && _vm->_events->_rateCounter < rate2);
|
||||
}
|
||||
|
||||
if (!_vm->_events->_escKeyFl) {
|
||||
_vm->_events->_rateCounter = 0;
|
||||
if (*screenP != kByteStop)
|
||||
_vm->_graphicsMan->copyVideoVbe16(screenP);
|
||||
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE && !_vm->_events->_escKeyFl) {
|
||||
// Do post-animation delay
|
||||
do {
|
||||
if (_vm->_events->_escKeyFl)
|
||||
break;
|
||||
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
} while (_vm->_events->_rateCounter < rate3);
|
||||
}
|
||||
|
||||
if (!_vm->_events->_escKeyFl) {
|
||||
_vm->_events->_rateCounter = 0;
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
}
|
||||
|
||||
if (_vm->_graphicsMan->_fadingFl) {
|
||||
byte *screenCopy = _vm->_globals->allocMemory(307200);
|
||||
|
||||
f.seek(6);
|
||||
f.read(_vm->_graphicsMan->_palette, 800);
|
||||
f.skip(4);
|
||||
nbytes = f.readUint32LE();
|
||||
f.skip(14);
|
||||
f.read(screenP, nbytes);
|
||||
|
||||
memcpy(screenCopy, screenP, 307200);
|
||||
|
||||
for (;;) {
|
||||
byte imageStr[17];
|
||||
if (f.read(imageStr, 16) != 16)
|
||||
break;
|
||||
imageStr[16] = 0;
|
||||
|
||||
if (strncmp((const char *)imageStr, "IMAGE=", 6))
|
||||
break;
|
||||
|
||||
f.read(screenP, READ_LE_UINT32(imageStr + 8));
|
||||
if (*screenP != kByteStop)
|
||||
_vm->_graphicsMan->copyWinscanVbe3(screenP, screenCopy);
|
||||
}
|
||||
_vm->_graphicsMan->fadeOutDefaultLength(screenCopy);
|
||||
_vm->_globals->freeMemory(screenCopy);
|
||||
}
|
||||
|
||||
_vm->_graphicsMan->_fadingFl = false;
|
||||
f.close();
|
||||
_vm->_graphicsMan->_skipVideoLockFl = false;
|
||||
|
||||
_vm->_events->mouseOn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Play Animation, type 2
|
||||
*/
|
||||
void AnimationManager::playAnim2(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3) {
|
||||
int oldScrollPosX = 0;
|
||||
byte *screenP = nullptr;
|
||||
Common::File f;
|
||||
|
||||
if (_vm->shouldQuit())
|
||||
return;
|
||||
|
||||
_vm->_events->mouseOff();
|
||||
|
||||
while (!_vm->shouldQuit()) {
|
||||
memcpy(_vm->_graphicsMan->_oldPalette, _vm->_graphicsMan->_palette, 769);
|
||||
|
||||
_vm->_graphicsMan->backupScreen();
|
||||
|
||||
if (!_vm->_graphicsMan->_lineNbr)
|
||||
_vm->_graphicsMan->_scrollOffset = 0;
|
||||
|
||||
screenP = _vm->_graphicsMan->_backBuffer;
|
||||
if (!f.open(hiresName)) {
|
||||
if (!f.open(lowresName))
|
||||
error("Error opening files: %s - %s", hiresName.toString().c_str(), lowresName.toString().c_str());
|
||||
}
|
||||
|
||||
f.skip(6);
|
||||
f.read(_vm->_graphicsMan->_palette, 800);
|
||||
f.skip(4);
|
||||
size_t nbytes = f.readUint32LE();
|
||||
f.skip(14);
|
||||
|
||||
f.read(screenP, nbytes);
|
||||
|
||||
_vm->_graphicsMan->clearPalette();
|
||||
oldScrollPosX = _vm->_graphicsMan->_scrollPosX;
|
||||
_vm->_graphicsMan->setScreenWidth(SCREEN_WIDTH);
|
||||
_vm->_graphicsMan->scrollScreen(0);
|
||||
_vm->_graphicsMan->clearScreen();
|
||||
_vm->_graphicsMan->_maxX = SCREEN_WIDTH;
|
||||
|
||||
_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
|
||||
_vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
|
||||
_vm->_events->_rateCounter = 0;
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_vm->_soundMan->loadAnimSound();
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
while (!_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate1) {
|
||||
_vm->_events->refreshEvents();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_vm->_events->_escKeyFl) {
|
||||
_vm->_events->_rateCounter = 0;
|
||||
int frameNumber = 0;
|
||||
for (;;) {
|
||||
if (_vm->_events->_escKeyFl)
|
||||
break;
|
||||
++frameNumber;
|
||||
_vm->_soundMan->playAnimSound(frameNumber);
|
||||
byte imageStr[17];
|
||||
if (f.read(imageStr, 16) != 16)
|
||||
break;
|
||||
imageStr[16] = 0;
|
||||
|
||||
if (strncmp((const char *)imageStr, "IMAGE=", 6))
|
||||
break;
|
||||
|
||||
f.read(screenP, READ_LE_UINT32(imageStr + 8));
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
while (!_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate2) {
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_events->_rateCounter = 0;
|
||||
if (*screenP != kByteStop)
|
||||
_vm->_graphicsMan->copyVideoVbe16(screenP);
|
||||
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
}
|
||||
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
while (!_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate3) {
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphicsMan->_skipVideoLockFl = false;
|
||||
f.close();
|
||||
|
||||
if (_vm->_graphicsMan->_fadingFl) {
|
||||
f.seek(6);
|
||||
f.read(_vm->_graphicsMan->_palette, 800);
|
||||
f.skip(4);
|
||||
size_t nbytes = f.readUint32LE();
|
||||
f.skip(14);
|
||||
f.read(screenP, nbytes);
|
||||
byte *ptra = _vm->_globals->allocMemory(307200);
|
||||
memcpy(ptra, screenP, 307200);
|
||||
|
||||
for (;;) {
|
||||
byte imageStr[17];
|
||||
if (f.read(imageStr, 16) != 16)
|
||||
break;
|
||||
imageStr[16] = 0;
|
||||
|
||||
if (strncmp((const char *)imageStr, "IMAGE=", 6))
|
||||
break;
|
||||
|
||||
f.read(screenP, READ_LE_UINT32(imageStr + 8));
|
||||
if (*screenP != kByteStop)
|
||||
_vm->_graphicsMan->copyWinscanVbe3(screenP, ptra);
|
||||
}
|
||||
_vm->_graphicsMan->fadeOutDefaultLength(ptra);
|
||||
ptra = _vm->_globals->freeMemory(ptra);
|
||||
}
|
||||
_vm->_graphicsMan->_fadingFl = false;
|
||||
|
||||
_vm->_graphicsMan->restoreScreen();
|
||||
|
||||
memcpy(_vm->_graphicsMan->_palette, _vm->_graphicsMan->_oldPalette, 769);
|
||||
_vm->_graphicsMan->clearPalette();
|
||||
_vm->_graphicsMan->clearScreen();
|
||||
|
||||
_vm->_graphicsMan->_scrollPosX = oldScrollPosX;
|
||||
_vm->_graphicsMan->scrollScreen(oldScrollPosX);
|
||||
if (_vm->_graphicsMan->_largeScreenFl) {
|
||||
_vm->_graphicsMan->setScreenWidth(2 * SCREEN_WIDTH);
|
||||
_vm->_graphicsMan->_maxX = 2 * SCREEN_WIDTH;
|
||||
_vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_frontBuffer, _vm->_events->_startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
|
||||
} else {
|
||||
_vm->_graphicsMan->setScreenWidth(SCREEN_WIDTH);
|
||||
_vm->_graphicsMan->_maxX = SCREEN_WIDTH;
|
||||
_vm->_graphicsMan->clearScreen();
|
||||
_vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_frontBuffer, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
|
||||
}
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
|
||||
_vm->_graphicsMan->fadeInShort();
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
|
||||
_vm->_events->mouseOn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Animation
|
||||
*/
|
||||
void AnimationManager::loadAnim(const Common::Path &animName) {
|
||||
clearAnim();
|
||||
|
||||
Common::Path filename(animName);
|
||||
filename.appendInPlace(".ANI");
|
||||
Common::File f;
|
||||
if (!f.open(filename))
|
||||
error("Failed to open %s", filename.toString().c_str());
|
||||
|
||||
int filesize = f.size();
|
||||
int nbytes = filesize - 115;
|
||||
|
||||
char header[10];
|
||||
char dummyBuf[15];
|
||||
char filename1[15];
|
||||
char filename2[15];
|
||||
char filename3[15];
|
||||
char filename4[15];
|
||||
char filename5[15];
|
||||
char filename6[15];
|
||||
|
||||
f.read(header, 10);
|
||||
f.read(dummyBuf, 15);
|
||||
f.read(filename1, 15);
|
||||
f.read(filename2, 15);
|
||||
f.read(filename3, 15);
|
||||
f.read(filename4, 15);
|
||||
f.read(filename5, 15);
|
||||
f.read(filename6, 15);
|
||||
|
||||
if (READ_BE_UINT32(header) != MKTAG('A', 'N', 'I', 'S'))
|
||||
error("Invalid animation File: %s", filename.toString().c_str());
|
||||
|
||||
const char *files[6] = { &filename1[0], &filename2[0], &filename3[0], &filename4[0],
|
||||
&filename5[0], &filename6[0] };
|
||||
|
||||
for (int idx = 0; idx <= 5; ++idx) {
|
||||
if (files[idx][0]) {
|
||||
if (!f.exists(files[idx]))
|
||||
error("Missing file %s in animation File: %s", files[idx], filename.toString().c_str());
|
||||
if (loadSpriteBank(idx + 1, files[idx]))
|
||||
error("Invalid sprite bank in animation File: %s", filename.toString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
byte *data = _vm->_globals->allocMemory(nbytes + 1);
|
||||
f.read(data, nbytes);
|
||||
f.close();
|
||||
|
||||
for (int idx = 1; idx <= 20; ++idx)
|
||||
searchAnim(data, idx, nbytes);
|
||||
|
||||
_vm->_globals->freeMemory(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear animation
|
||||
*/
|
||||
void AnimationManager::clearAnim() {
|
||||
for (int idx = 0; idx < 35; ++idx) {
|
||||
_animBqe[idx]._data = _vm->_globals->freeMemory(_animBqe[idx]._data);
|
||||
_animBqe[idx]._enabledFl = false;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < 8; ++idx) {
|
||||
Bank[idx]._data = _vm->_globals->freeMemory(Bank[idx]._data);
|
||||
Bank[idx]._loadedFl = false;
|
||||
Bank[idx]._filename = "";
|
||||
Bank[idx]._fileHeader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Sprite Bank
|
||||
*/
|
||||
int AnimationManager::loadSpriteBank(int idx, const Common::Path &filename) {
|
||||
int result = 0;
|
||||
Bank[idx]._loadedFl = true;
|
||||
Bank[idx]._filename = filename;
|
||||
|
||||
byte *fileDataPtr = _vm->_fileIO->loadFile(filename);
|
||||
|
||||
Bank[idx]._fileHeader = 0;
|
||||
if (fileDataPtr[1] == 'L' && fileDataPtr[2] == 'E')
|
||||
Bank[idx]._fileHeader = 1;
|
||||
else if (fileDataPtr[1] == 'O' && fileDataPtr[2] == 'R')
|
||||
Bank[idx]._fileHeader = 2;
|
||||
|
||||
if (!Bank[idx]._fileHeader) {
|
||||
_vm->_globals->freeMemory(fileDataPtr);
|
||||
Bank[idx]._loadedFl = false;
|
||||
result = -1;
|
||||
}
|
||||
|
||||
Bank[idx]._data = fileDataPtr;
|
||||
|
||||
int objectDataIdx = 0;
|
||||
for(objectDataIdx = 0; objectDataIdx <= 249; objectDataIdx++) {
|
||||
int width = _vm->_objectsMan->getWidth(fileDataPtr, objectDataIdx);
|
||||
int height = _vm->_objectsMan->getHeight(fileDataPtr, objectDataIdx);
|
||||
if (!width && !height)
|
||||
break;
|
||||
}
|
||||
|
||||
if (objectDataIdx > 249) {
|
||||
_vm->_globals->freeMemory(fileDataPtr);
|
||||
Bank[idx]._loadedFl = false;
|
||||
result = -2;
|
||||
}
|
||||
Bank[idx]._objDataIdx = objectDataIdx;
|
||||
|
||||
Common::String ofsFilename = Bank[idx]._filename.baseName();
|
||||
char ch;
|
||||
do {
|
||||
ch = ofsFilename.lastChar();
|
||||
ofsFilename.deleteLastChar();
|
||||
} while (ch != '.');
|
||||
ofsFilename += ".OFS";
|
||||
|
||||
Common::Path ofsPathname(Bank[idx]._filename.getParent().appendComponent(ofsFilename));
|
||||
Common::File f;
|
||||
if (f.exists(ofsPathname)) {
|
||||
byte *ofsData = _vm->_fileIO->loadFile(ofsPathname);
|
||||
byte *curOfsData = ofsData;
|
||||
for (int objIdx = 0; objIdx < Bank[idx]._objDataIdx; ++objIdx, curOfsData += 8) {
|
||||
int x1 = READ_LE_INT16(curOfsData);
|
||||
int y1 = READ_LE_INT16(curOfsData + 2);
|
||||
int x2 = READ_LE_INT16(curOfsData + 4);
|
||||
int y2 = READ_LE_INT16(curOfsData + 6);
|
||||
|
||||
_vm->_objectsMan->setOffsetXY(Bank[idx]._data, objIdx, x1, y1, 0);
|
||||
if (Bank[idx]._fileHeader == 2)
|
||||
_vm->_objectsMan->setOffsetXY(Bank[idx]._data, objIdx, x2, y2, 1);
|
||||
}
|
||||
|
||||
_vm->_globals->freeMemory(ofsData);
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search Animation
|
||||
*/
|
||||
void AnimationManager::searchAnim(const byte *data, int animIndex, int bufSize) {
|
||||
for (int dataIdx = 0; dataIdx <= bufSize; dataIdx++) {
|
||||
if (READ_BE_UINT32(&data[dataIdx]) == MKTAG('A', 'N', 'I', 'M')) {
|
||||
int entryIndex = data[dataIdx + 4];
|
||||
if (animIndex == entryIndex) {
|
||||
int curBufferPos = dataIdx + 5;
|
||||
int count = 0;
|
||||
bool innerLoopCond = false;
|
||||
do {
|
||||
if (READ_BE_UINT32(&data[curBufferPos]) == MKTAG('A', 'N', 'I', 'M') || READ_BE_UINT24(&data[curBufferPos]) == MKTAG24('F', 'I', 'N'))
|
||||
innerLoopCond = true;
|
||||
if (bufSize < curBufferPos) {
|
||||
_animBqe[animIndex]._enabledFl = false;
|
||||
_animBqe[animIndex]._data = nullptr;
|
||||
return;
|
||||
}
|
||||
++curBufferPos;
|
||||
++count;
|
||||
} while (!innerLoopCond);
|
||||
_animBqe[animIndex]._data = _vm->_globals->allocMemory(count + 50);
|
||||
_animBqe[animIndex]._enabledFl = true;
|
||||
memcpy(_animBqe[animIndex]._data, data + dataIdx + 5, 20);
|
||||
|
||||
byte *dataP = _animBqe[animIndex]._data;
|
||||
int curDestDataIndx = 20;
|
||||
int curSrcDataIndx = dataIdx + 25;
|
||||
|
||||
for (int i = 0; i <= 4999; i++) {
|
||||
memcpy(dataP + curDestDataIndx, data + curSrcDataIndx, 10);
|
||||
if (!READ_LE_UINT16(data + curSrcDataIndx + 4))
|
||||
break;
|
||||
curDestDataIndx += 10;
|
||||
curSrcDataIndx += 10;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (READ_BE_UINT24(&data[dataIdx]) == MKTAG24('F', 'I', 'N'))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Play sequence
|
||||
*/
|
||||
void AnimationManager::playSequence(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipEscFl, bool skipSeqFl, bool noColFl) {
|
||||
if (_vm->shouldQuit())
|
||||
return;
|
||||
|
||||
_vm->_events->_mouseFl = false;
|
||||
if (!noColFl) {
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
|
||||
_vm->_graphicsMan->backupScreen();
|
||||
|
||||
if (!_vm->_graphicsMan->_lineNbr)
|
||||
_vm->_graphicsMan->_scrollOffset = 0;
|
||||
}
|
||||
byte *screenP = _vm->_graphicsMan->_backBuffer;
|
||||
Common::File f;
|
||||
if (!f.open(file))
|
||||
error("Error opening file - %s", file.toString().c_str());
|
||||
|
||||
f.skip(6);
|
||||
f.read(_vm->_graphicsMan->_palette, 800);
|
||||
f.skip(4);
|
||||
size_t nbytes = f.readUint32LE();
|
||||
f.skip(14);
|
||||
f.read(screenP, nbytes);
|
||||
|
||||
if (skipSeqFl) {
|
||||
if (!_vm->getIsDemo()) {
|
||||
_vm->_graphicsMan->setColorPercentage(252, 100, 100, 100);
|
||||
_vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
|
||||
_vm->_graphicsMan->setColorPercentage(251, 100, 100, 100);
|
||||
_vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
|
||||
}
|
||||
_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
|
||||
} else {
|
||||
_vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
}
|
||||
bool skipFl = false;
|
||||
if (noColFl)
|
||||
_vm->_graphicsMan->fadeInDefaultLength(screenP);
|
||||
_vm->_events->_rateCounter = 0;
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_vm->_soundMan->loadAnimSound();
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
do {
|
||||
if (_vm->shouldQuit() || (_vm->_events->_escKeyFl && !skipEscFl)) {
|
||||
skipFl = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
} while (_vm->_events->_rateCounter < rate1);
|
||||
}
|
||||
_vm->_events->_rateCounter = 0;
|
||||
if (!skipFl) {
|
||||
int soundNumber = 0;
|
||||
for (;;) {
|
||||
++soundNumber;
|
||||
_vm->_soundMan->playAnimSound(soundNumber);
|
||||
byte imageStr[17];
|
||||
if (f.read(imageStr, 16) != 16)
|
||||
break;
|
||||
imageStr[16] = 0;
|
||||
|
||||
if (strncmp((const char *)imageStr, "IMAGE=", 6))
|
||||
break;
|
||||
|
||||
f.read(screenP, READ_LE_UINT32(imageStr + 8));
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
do {
|
||||
if (_vm->shouldQuit() || (_vm->_events->_escKeyFl && !skipEscFl)) {
|
||||
skipFl = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
} while (_vm->_events->_rateCounter < rate2);
|
||||
}
|
||||
|
||||
if (skipFl)
|
||||
break;
|
||||
|
||||
_vm->_events->_rateCounter = 0;
|
||||
if (*screenP != kByteStop)
|
||||
_vm->_graphicsMan->copyVideoVbe16a(screenP);
|
||||
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
}
|
||||
}
|
||||
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE && !skipFl) {
|
||||
do {
|
||||
if (_vm->shouldQuit() || (_vm->_events->_escKeyFl && !skipEscFl)) {
|
||||
skipFl = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
} while (_vm->_events->_rateCounter < rate3);
|
||||
}
|
||||
|
||||
if (!skipFl)
|
||||
_vm->_events->_rateCounter = 0;
|
||||
|
||||
_vm->_graphicsMan->_skipVideoLockFl = false;
|
||||
f.close();
|
||||
|
||||
if (!noColFl) {
|
||||
_vm->_graphicsMan->restoreScreen();
|
||||
|
||||
_vm->_events->_mouseFl = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Play Sequence type 2
|
||||
*/
|
||||
void AnimationManager::playSequence2(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) {
|
||||
byte *screenP;
|
||||
Common::File f;
|
||||
|
||||
if (_vm->shouldQuit())
|
||||
return;
|
||||
|
||||
_vm->_events->_mouseFl = false;
|
||||
screenP = _vm->_graphicsMan->_backBuffer;
|
||||
|
||||
if (!f.open(file))
|
||||
error("File not found - %s", file.toString().c_str());
|
||||
|
||||
f.skip(6);
|
||||
f.read(_vm->_graphicsMan->_palette, 800);
|
||||
f.skip(4);
|
||||
size_t nbytes = f.readUint32LE();
|
||||
f.skip(14);
|
||||
f.read(screenP, nbytes);
|
||||
|
||||
if (skipSeqFl) {
|
||||
_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
|
||||
} else {
|
||||
_vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
|
||||
_vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
|
||||
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
}
|
||||
_vm->_events->_rateCounter = 0;
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_vm->_soundMan->loadAnimSound();
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
do {
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
} while (!_vm->shouldQuit() && !_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate1);
|
||||
}
|
||||
|
||||
if (!_vm->_events->_escKeyFl) {
|
||||
_vm->_events->_rateCounter = 0;
|
||||
int frameNumber = 0;
|
||||
while (!_vm->shouldQuit()) {
|
||||
_vm->_soundMan->playAnimSound(frameNumber++);
|
||||
|
||||
byte imageStr[17];
|
||||
if (f.read(imageStr, 16) != 16)
|
||||
break;
|
||||
imageStr[16] = 0;
|
||||
|
||||
if (strncmp((const char *)imageStr, "IMAGE=", 6))
|
||||
break;
|
||||
|
||||
f.read(screenP, READ_LE_UINT32(imageStr + 8));
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
do {
|
||||
_vm->_events->refreshEvents();
|
||||
} while (!_vm->shouldQuit() && !_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate2);
|
||||
}
|
||||
|
||||
_vm->_events->_rateCounter = 0;
|
||||
if (*screenP != kByteStop)
|
||||
_vm->_graphicsMan->copyVideoVbe16a(screenP);
|
||||
|
||||
_vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
}
|
||||
}
|
||||
|
||||
if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) {
|
||||
// Wait for third rate delay
|
||||
do {
|
||||
_vm->_events->refreshEvents();
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
} while (!_vm->shouldQuit() && !_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate3);
|
||||
}
|
||||
|
||||
_vm->_events->_rateCounter = 0;
|
||||
|
||||
if (_vm->_graphicsMan->_fadingFl) {
|
||||
byte *ptra = _vm->_globals->allocMemory(307200);
|
||||
|
||||
f.seek(6);
|
||||
f.read(_vm->_graphicsMan->_palette, 800);
|
||||
f.skip(4);
|
||||
nbytes = f.readUint32LE();
|
||||
f.skip(14);
|
||||
f.read(screenP, nbytes);
|
||||
|
||||
memcpy(ptra, screenP, 307200);
|
||||
for (;;) {
|
||||
byte imageStr[17];
|
||||
if (f.read(imageStr, 16) != 16)
|
||||
break;
|
||||
imageStr[16] = 0;
|
||||
|
||||
if (strncmp((const char *)imageStr, "IMAGE=", 6))
|
||||
break;
|
||||
|
||||
f.read(screenP, READ_LE_UINT32(imageStr + 8));
|
||||
if (*screenP != kByteStop)
|
||||
_vm->_graphicsMan->copyWinscanVbe(screenP, ptra);
|
||||
}
|
||||
_vm->_graphicsMan->fadeOutDefaultLength(ptra);
|
||||
ptra = _vm->_globals->freeMemory(ptra);
|
||||
}
|
||||
_vm->_graphicsMan->_fadingFl = false;
|
||||
|
||||
f.close();
|
||||
_vm->_events->_mouseFl = true;
|
||||
}
|
||||
|
||||
void AnimationManager::initAnimBqe() {
|
||||
for (int idx = 0; idx < 35; ++idx) {
|
||||
_animBqe[idx]._data = nullptr;
|
||||
_animBqe[idx]._enabledFl = false;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < 8; ++idx) {
|
||||
Bank[idx]._data = nullptr;
|
||||
Bank[idx]._loadedFl = false;
|
||||
Bank[idx]._filename = "";
|
||||
Bank[idx]._fileHeader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
77
engines/hopkins/anim.h
Normal file
77
engines/hopkins/anim.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 HOPKINS_ANIM_H
|
||||
#define HOPKINS_ANIM_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/path.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
struct BankItem {
|
||||
byte *_data;
|
||||
bool _loadedFl;
|
||||
Common::Path _filename;
|
||||
int _fileHeader;
|
||||
int _objDataIdx;
|
||||
};
|
||||
|
||||
struct BqeAnimItem {
|
||||
byte *_data;
|
||||
bool _enabledFl;
|
||||
};
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
class AnimationManager {
|
||||
private:
|
||||
bool _clearAnimationFl;
|
||||
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
void initAnimBqe();
|
||||
int loadSpriteBank(int idx, const Common::Path &filename);
|
||||
void searchAnim(const byte *data, int animIndex, int count);
|
||||
|
||||
public:
|
||||
BqeAnimItem _animBqe[35];
|
||||
BankItem Bank[8];
|
||||
|
||||
AnimationManager(HopkinsEngine *vm);
|
||||
void clearAll();
|
||||
|
||||
void loadAnim(const Common::Path &animName);
|
||||
void clearAnim();
|
||||
void playAnim(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl = false);
|
||||
void playAnim2(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3);
|
||||
void playSequence(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipEscFl, bool skipSeqFl, bool noColFl = false);
|
||||
void playSequence2(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl = false);
|
||||
|
||||
void setClearAnimFlag() { _clearAnimationFl = true; }
|
||||
void unsetClearAnimFlag() { _clearAnimationFl = false; }
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_ANIM_H */
|
||||
1271
engines/hopkins/computer.cpp
Normal file
1271
engines/hopkins/computer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
105
engines/hopkins/computer.h
Normal file
105
engines/hopkins/computer.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HOPKINS_COMPUTER_H
|
||||
#define HOPKINS_COMPUTER_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
enum ComputerEnum { COMPUTER_HOPKINS = 1, COMPUTER_SAMANTHA = 2, COMPUTER_PUBLIC = 3 };
|
||||
|
||||
class ComputerManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
struct MenuItem {
|
||||
int _lineSize;
|
||||
char _line[90];
|
||||
};
|
||||
|
||||
struct ScoreItem {
|
||||
Common::String _name;
|
||||
Common::String _score;
|
||||
};
|
||||
|
||||
MenuItem _menuText[50];
|
||||
char _inputBuf[200];
|
||||
ScoreItem _score[6];
|
||||
int _textColor;
|
||||
Common::Point _textPosition;
|
||||
Common::Point _ballPosition;
|
||||
byte *_breakoutSpr;
|
||||
int16 *_breakoutLevel;
|
||||
int _breakoutBrickNbr;
|
||||
int _breakoutScore;
|
||||
int _breakoutLives;
|
||||
int _breakoutSpeed;
|
||||
bool _ballRightFl;
|
||||
bool _ballUpFl;
|
||||
int _breakoutLevelNbr;
|
||||
int _padPositionX;
|
||||
int _lowestHiScore;
|
||||
int _minBreakoutMoveSpeed;
|
||||
int _maxBreakoutMoveSpeed;
|
||||
int _lastBreakoutMoveSpeed;
|
||||
|
||||
void loadMenu();
|
||||
void restoreFBIRoom();
|
||||
void setVideoMode();
|
||||
void setTextMode();
|
||||
void clearScreen();
|
||||
void setTextColor(int col);
|
||||
void setTextPosition(int yp, int xp);
|
||||
void outText(const Common::String &msg);
|
||||
void outText2(const Common::String &msg);
|
||||
void readText(int idx);
|
||||
void loadHiscore();
|
||||
void newLevel();
|
||||
void setModeVGA256();
|
||||
void displayLives();
|
||||
void displayBricks();
|
||||
void displayGamesSubMenu();
|
||||
int displayHiscores();
|
||||
void displayHiscoreLine(const byte *objectData, int x, int y, int curChar);
|
||||
void displayMessage(int xp, int yp, int textIdx);
|
||||
void displayScore();
|
||||
void displayScoreChar(int charPos, int charDisp);
|
||||
void getScoreName();
|
||||
void playBreakout();
|
||||
int moveBall();
|
||||
void saveScore();
|
||||
void checkBallCollisions();
|
||||
|
||||
public:
|
||||
ComputerManager(HopkinsEngine *vm);
|
||||
|
||||
void showComputer(ComputerEnum mode);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_COMPUTER_H */
|
||||
3
engines/hopkins/configure.engine
Normal file
3
engines/hopkins/configure.engine
Normal 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 hopkins "Hopkins FBI" yes "" "" "16bit highres"
|
||||
4
engines/hopkins/credits.pl
Normal file
4
engines/hopkins/credits.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
begin_section("Hopkins");
|
||||
add_person("Arnaud Boutonné", "Strangerke", "");
|
||||
add_person("Paul Gilbert", "dreammaster", "");
|
||||
end_section();
|
||||
89
engines/hopkins/debugger.cpp
Normal file
89
engines/hopkins/debugger.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hopkins/debugger.h"
|
||||
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/graphics.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
Debugger::Debugger(HopkinsEngine *vm) : GUI::Debugger() {
|
||||
_vm = vm;
|
||||
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
|
||||
registerCmd("rects", WRAP_METHOD(Debugger, cmd_DirtyRects));
|
||||
registerCmd("teleport", WRAP_METHOD(Debugger, cmd_Teleport));
|
||||
registerCmd("show_room", WRAP_METHOD(Debugger, cmd_ShowCurrentRoom));
|
||||
registerCmd("zones", WRAP_METHOD(Debugger, cmd_Zones));
|
||||
registerCmd("lines", WRAP_METHOD(Debugger, cmd_Lines));
|
||||
}
|
||||
|
||||
// Turns dirty rects on or off
|
||||
bool Debugger::cmd_DirtyRects(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("%s: [on | off]\n", argv[0]);
|
||||
return true;
|
||||
} else {
|
||||
_vm->_graphicsMan->_showDirtyRects = !strcmp(argv[1], "on");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Change room number
|
||||
bool Debugger::cmd_Teleport(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("%s: [Room number]\n", argv[0]);
|
||||
return true;
|
||||
} else {
|
||||
_vm->_globals->_exitId = atoi(argv[1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Display room number
|
||||
bool Debugger::cmd_ShowCurrentRoom(int argc, const char **argv) {
|
||||
debugPrintf("Current room: %d\n", _vm->_globals->_curRoomNum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_Zones(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("%s: [on | off]\n", argv[0]);
|
||||
return true;
|
||||
} else {
|
||||
_vm->_graphicsMan->_showZones = !strcmp(argv[1], "on");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Debugger::cmd_Lines(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("%s: [on | off]\n", argv[0]);
|
||||
return true;
|
||||
} else {
|
||||
_vm->_graphicsMan->_showLines = !strcmp(argv[1], "on");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Hopkins
|
||||
49
engines/hopkins/debugger.h
Normal file
49
engines/hopkins/debugger.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HOPKINS_DEBUGGER_H
|
||||
#define HOPKINS_DEBUGGER_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
class Debugger : public GUI::Debugger {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
public:
|
||||
Debugger(HopkinsEngine *vm);
|
||||
~Debugger() override {}
|
||||
|
||||
bool cmd_DirtyRects(int argc, const char **argv);
|
||||
bool cmd_Teleport(int argc, const char **argv);
|
||||
bool cmd_ShowCurrentRoom(int argc, const char **argv);
|
||||
bool cmd_Zones(int argc, const char **argv);
|
||||
bool cmd_Lines(int argc, const char **argv);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif
|
||||
72
engines/hopkins/detection.cpp
Normal file
72
engines/hopkins/detection.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "hopkins/detection.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
|
||||
static const DebugChannelDef debugFlagList[] = {
|
||||
{Hopkins::kDebugPath, "Path", "Pathfinding debug level"},
|
||||
{Hopkins::kDebugGraphics, "Graphics", "Graphics debug level"},
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
static const PlainGameDescriptor hopkinsGames[] = {
|
||||
{"hopkins", "Hopkins FBI"},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
#include "hopkins/detection_tables.h"
|
||||
|
||||
const static char *const directoryGlobs[] = {
|
||||
"voice",
|
||||
"link",
|
||||
nullptr
|
||||
};
|
||||
|
||||
class HopkinsMetaEngineDetection : public AdvancedMetaEngineDetection<Hopkins::HopkinsGameDescription> {
|
||||
public:
|
||||
HopkinsMetaEngineDetection() : AdvancedMetaEngineDetection(Hopkins::gameDescriptions, hopkinsGames) {
|
||||
_maxScanDepth = 3;
|
||||
_directoryGlobs = directoryGlobs;
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "hopkins";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Hopkins FBI";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Hopkins FBI (C) 1997-2003 MP Entertainment";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return debugFlagList;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
REGISTER_PLUGIN_STATIC(HOPKINS_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, HopkinsMetaEngineDetection);
|
||||
38
engines/hopkins/detection.h
Normal file
38
engines/hopkins/detection.h
Normal 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 HOPKINS_DETECTION_H
|
||||
#define HOPKINS_DETECTION_H
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
struct HopkinsGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
};
|
||||
|
||||
#define GAMEOPTION_GORE_DEFAULT_ON GUIO_GAMEOPTIONS1
|
||||
#define GAMEOPTION_GORE_DEFAULT_OFF GUIO_GAMEOPTIONS2
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif // HOPKINS_DETECTION_H
|
||||
176
engines/hopkins/detection_tables.h
Normal file
176
engines/hopkins/detection_tables.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/* 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 Hopkins {
|
||||
|
||||
static const HopkinsGameDescription gameDescriptions[] = {
|
||||
{
|
||||
// Hopkins FBI Linux Demo UK 1.00 and 1.02
|
||||
{
|
||||
"hopkins",
|
||||
"Demo",
|
||||
AD_ENTRY1s("RES_VAN.RES", "29414c05be8f9fe794c61572a65def12", 16060544),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformLinux,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI OS/2, provided by Strangerke
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY2s("ENG_VOI.RES", "fa5789d1d8c19d160bce44a33e742fdf", 66860711,
|
||||
"CREAN.TXT", "e13aa69d9e043f066776e1d0ef98fdf5", 1871),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformOS2,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI BeOS, provided by Strangerke & Eriktorbjorn
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("ENG_VOI.RES", "fa5789d1d8c19d160bce44a33e742fdf", 66860711),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformBeOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Win95 Spanish
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("RES_VES.RES", "77ee08896466ae88cc1af3bf1a0bf78c", 32882302),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Win95 UK, provided by Strangerke, alexbevi, greencis
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("RES_VAN.RES", "f1693ac0b0859c8ecd8cb30ff43cf55f", 38296346),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_OFF, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Win95 RU, provided by greencis in bug #6324
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("res_van.res", "bf17c710e184a25a6c8e9d1d9503c38e", 32197685),
|
||||
Common::RU_RUS,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Linux, provided by Strangerke
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("RES_VFR.RES", "0490d4d1aa71075ebf71cc79e5dc7894", 39817945),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformLinux,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Linux, provided by Strangerke
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("RES_VAN.RES", "29414c05be8f9fe794c61572a65def12", 38832455),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformLinux,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Win95, French, provided by SylvainTV
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("RES_VFR.RES", "b8a3849063c9eeefe80e82cfce1ad3cd", 39269361),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Win95 Polish, provided by Paput in bug #6511
|
||||
{
|
||||
"hopkins",
|
||||
0,
|
||||
AD_ENTRY1s("RES_VAN.RES", "f2fec5172e4a7a9d35cb2a5f948ef6a9", 39400865),
|
||||
Common::PL_POL,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_OFF, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
// Hopkins FBI Win95 Demo, provided by Strangerke
|
||||
// CHECKME: No voice! a second file is required though... Also, it has multi-language support
|
||||
{
|
||||
"hopkins",
|
||||
"Demo",
|
||||
AD_ENTRY1s("Hopkins.exe", "0c9ebfe371f4dcf84a49f333f04839a0", 376897),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_ON, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{
|
||||
// Hopkins FBI Win95 Polish Demo, provided by Strangerke
|
||||
{
|
||||
"hopkins",
|
||||
"Demo",
|
||||
AD_ENTRY1s("RES_VAN.RES", "8262cfba261c200af4451902689dffe0", 12233202),
|
||||
Common::PL_POL,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GAMEOPTION_GORE_DEFAULT_OFF, GUIO_NOMIDI)
|
||||
},
|
||||
},
|
||||
{ AD_TABLE_END_MARKER }
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
799
engines/hopkins/dialogs.cpp
Normal file
799
engines/hopkins/dialogs.cpp
Normal file
@@ -0,0 +1,799 @@
|
||||
/* 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 "hopkins/dialogs.h"
|
||||
|
||||
#include "hopkins/events.h"
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/graphics.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
#include "hopkins/sound.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/events.h"
|
||||
#include "common/file.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
DialogsManager::DialogsManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
_inventFl = false;
|
||||
_inventDisplayedFl = false;
|
||||
_removeInventFl = false;
|
||||
_inventX = _inventY = 0;
|
||||
_oldInventX = 0;
|
||||
_inventWidth = _inventHeight = 0;
|
||||
_inventWin1 = nullptr;
|
||||
_inventBuf2 = nullptr;
|
||||
_inventoryIcons = nullptr;
|
||||
}
|
||||
|
||||
DialogsManager::~DialogsManager() {
|
||||
_vm->_globals->freeMemory(_inventWin1);
|
||||
_vm->_globals->freeMemory(_inventBuf2);
|
||||
_vm->_globals->freeMemory(_inventoryIcons);
|
||||
}
|
||||
|
||||
void DialogsManager::clearAll() {
|
||||
_inventWin1 = nullptr;
|
||||
_inventBuf2 = nullptr;
|
||||
}
|
||||
|
||||
void DialogsManager::loadIcons() {
|
||||
_inventoryIcons = _vm->_fileIO->loadFile("ICONE.SPR");
|
||||
}
|
||||
|
||||
void DialogsManager::drawInvent(Common::Point oldBorder, int oldBorderSpriteIndex, Common::Point newBorder, int newBorderSpriteIndex) {
|
||||
if (!_inventDisplayedFl)
|
||||
return;
|
||||
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, _inventWin1, _inventX, _inventY, _inventWidth, _inventHeight);
|
||||
if (oldBorder.x && oldBorder.y)
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _inventBuf2, oldBorder.x + 300, oldBorder.y + 300, oldBorderSpriteIndex + 1);
|
||||
if (newBorder.x && newBorder.y)
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _inventBuf2, newBorder.x + 300, newBorder.y + 300, newBorderSpriteIndex);
|
||||
_vm->_graphicsMan->addDirtyRect(_inventX, _inventY, _inventX + _inventWidth, _inventY + _inventHeight);
|
||||
}
|
||||
|
||||
void DialogsManager::showOptionsDialog() {
|
||||
_vm->_events->changeMouseCursor(0);
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
Common::Path filename;
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
|
||||
filename = "OPTION.SPR";
|
||||
else {
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_FR:
|
||||
filename = "OPTIFR.SPR";
|
||||
break;
|
||||
case LANG_EN:
|
||||
filename = "OPTIAN.SPR";
|
||||
break;
|
||||
case LANG_SP:
|
||||
filename = "OPTIES.SPR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_globals->_optionDialogSpr = _vm->_fileIO->loadFile(filename);
|
||||
_vm->_globals->_optionDialogFl = true;
|
||||
|
||||
int scrollOffset = _vm->_graphicsMan->_scrollOffset;
|
||||
bool doneFlag = false;
|
||||
do {
|
||||
if (_vm->_events->getMouseButton()) {
|
||||
Common::Point mousePos(_vm->_events->getMouseX(), _vm->_events->getMouseY());
|
||||
|
||||
if (!_vm->_soundMan->_musicOffFl) {
|
||||
if (mousePos.x >= scrollOffset + 300 && mousePos.y > 113 && mousePos.x <= scrollOffset + 327 && mousePos.y <= 138) {
|
||||
// Change the music volume
|
||||
++_vm->_soundMan->_musicVolume;
|
||||
|
||||
if (_vm->_soundMan->_musicVolume <= 12)
|
||||
_vm->_soundMan->playSoundFile("bruit2.wav");
|
||||
else
|
||||
_vm->_soundMan->_musicVolume = 12;
|
||||
_vm->_soundMan->setMODMusicVolume(_vm->_soundMan->_musicVolume);
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
|
||||
if (!_vm->_soundMan->_musicOffFl && mousePos.x >= scrollOffset + 331 && mousePos.y > 113 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 138) {
|
||||
--_vm->_soundMan->_musicVolume;
|
||||
if (_vm->_soundMan->_musicVolume >= 0)
|
||||
_vm->_soundMan->playSoundFile("bruit2.wav");
|
||||
else
|
||||
_vm->_soundMan->_musicVolume = 0;
|
||||
|
||||
_vm->_soundMan->setMODMusicVolume(_vm->_soundMan->_musicVolume);
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
}
|
||||
if (!_vm->_soundMan->_soundOffFl) {
|
||||
// increase volume
|
||||
if (mousePos.x >= scrollOffset + 300 && mousePos.y > 140 && mousePos.x <= scrollOffset + 327 && mousePos.y <= 165) {
|
||||
++_vm->_soundMan->_soundVolume;
|
||||
if (_vm->_soundMan->_soundVolume <= 16)
|
||||
_vm->_soundMan->playSoundFile("bruit2.wav");
|
||||
else
|
||||
_vm->_soundMan->_soundVolume = 16;
|
||||
_vm->_soundMan->setMODSampleVolume();
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
|
||||
// Decrease volume
|
||||
if (!_vm->_soundMan->_soundOffFl && mousePos.x >= scrollOffset + 331 && mousePos.y > 140 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 165) {
|
||||
--_vm->_soundMan->_soundVolume;
|
||||
if (_vm->_soundMan->_soundVolume >= 0)
|
||||
_vm->_soundMan->playSoundFile("bruit2.wav");
|
||||
else
|
||||
_vm->_soundMan->_soundVolume = 0;
|
||||
_vm->_soundMan->setMODSampleVolume();
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_vm->_soundMan->_voiceOffFl) {
|
||||
if (mousePos.x >= scrollOffset + 300 && mousePos.y > 167 && mousePos.x <= scrollOffset + 327 && mousePos.y <= 192) {
|
||||
++_vm->_soundMan->_voiceVolume;
|
||||
|
||||
if (_vm->_soundMan->_voiceVolume <= 16)
|
||||
_vm->_soundMan->playSoundFile("bruit2.wav");
|
||||
else
|
||||
_vm->_soundMan->_voiceVolume = 16;
|
||||
_vm->_soundMan->setMODVoiceVolume();
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
|
||||
if (!_vm->_soundMan->_voiceOffFl && mousePos.x >= scrollOffset + 331 && mousePos.y > 167 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 192) {
|
||||
--_vm->_soundMan->_voiceVolume;
|
||||
if (_vm->_soundMan->_voiceVolume >= 0)
|
||||
_vm->_soundMan->playSoundFile("bruit2.wav");
|
||||
else
|
||||
_vm->_soundMan->_voiceVolume = 0;
|
||||
_vm->_soundMan->setMODVoiceVolume();
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
}
|
||||
|
||||
if (mousePos.x >= scrollOffset + 431) {
|
||||
if (mousePos.y > 194 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 219)
|
||||
_vm->_soundMan->_textOffFl = !_vm->_soundMan->_textOffFl;
|
||||
|
||||
if (mousePos.x >= scrollOffset + 431) {
|
||||
if (mousePos.y > 167 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 192) {
|
||||
_vm->_soundMan->_voiceOffFl = !_vm->_soundMan->_voiceOffFl;
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
if (mousePos.x >= scrollOffset + 431) {
|
||||
if (mousePos.y > 113 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 138) {
|
||||
if (_vm->_soundMan->_musicOffFl) {
|
||||
_vm->_soundMan->_musicOffFl = false;
|
||||
_vm->_soundMan->setMODMusicVolume(_vm->_soundMan->_musicVolume);
|
||||
} else {
|
||||
_vm->_soundMan->_musicOffFl = true;
|
||||
_vm->_soundMan->setMODMusicVolume(0);
|
||||
}
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
|
||||
if (mousePos.x >= scrollOffset + 431 && mousePos.y > 140 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 165) {
|
||||
_vm->_soundMan->_soundOffFl = !_vm->_soundMan->_soundOffFl;
|
||||
|
||||
_vm->_soundMan->updateScummVMSoundSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mousePos.x >= scrollOffset + 175 && mousePos.y > 285 && mousePos.x <= scrollOffset + 281 && mousePos.y <= 310) {
|
||||
_vm->_globals->_exitId = 300;
|
||||
doneFlag = true;
|
||||
}
|
||||
if (mousePos.x >= scrollOffset + 355 && mousePos.y > 285 && mousePos.x <= scrollOffset + 490 && mousePos.y <= 310)
|
||||
doneFlag = true;
|
||||
if (mousePos.x >= scrollOffset + 300 && mousePos.y > 194 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 219) {
|
||||
switch (_vm->_graphicsMan->_scrollSpeed) {
|
||||
case 1:
|
||||
_vm->_graphicsMan->_scrollSpeed = 2;
|
||||
break;
|
||||
case 2:
|
||||
_vm->_graphicsMan->_scrollSpeed = 4;
|
||||
break;
|
||||
case 4:
|
||||
_vm->_graphicsMan->_scrollSpeed = 8;
|
||||
break;
|
||||
case 8:
|
||||
_vm->_graphicsMan->_scrollSpeed = 16;
|
||||
break;
|
||||
case 16:
|
||||
_vm->_graphicsMan->_scrollSpeed = 32;
|
||||
break;
|
||||
case 32:
|
||||
_vm->_graphicsMan->_scrollSpeed = 48;
|
||||
break;
|
||||
case 48:
|
||||
_vm->_graphicsMan->_scrollSpeed = 64;
|
||||
break;
|
||||
case 64:
|
||||
_vm->_graphicsMan->_scrollSpeed = 128;
|
||||
break;
|
||||
case 128:
|
||||
_vm->_graphicsMan->_scrollSpeed = 160;
|
||||
break;
|
||||
case 160:
|
||||
_vm->_graphicsMan->_scrollSpeed = 320;
|
||||
break;
|
||||
case 320:
|
||||
_vm->_graphicsMan->_scrollSpeed = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Values are blocked, thus handling the zone is useless
|
||||
//if (mousePos.x >= _vm->_graphicsManager->ofscroll + 348 && mousePos.y > 248 && mousePos.x <= _vm->_graphicsManager->ofscroll + 394 && mousePos.y <= 273)
|
||||
// _vm->_globals->_speed = 2;
|
||||
|
||||
if ( mousePos.x < scrollOffset + 165 || mousePos.x > scrollOffset + 496
|
||||
|| mousePos.y < 107 || mousePos.y > 318)
|
||||
doneFlag = true;
|
||||
}
|
||||
|
||||
if (_vm->_globals->_speed == 1)
|
||||
_vm->_globals->_menuSpeed = 6;
|
||||
else if (_vm->_globals->_speed == 2)
|
||||
_vm->_globals->_menuSpeed = 5;
|
||||
else if (_vm->_globals->_speed == 3)
|
||||
_vm->_globals->_menuSpeed = 4;
|
||||
|
||||
_vm->_globals->_menuTextOff = !_vm->_soundMan->_textOffFl ? 7 : 8;
|
||||
_vm->_globals->_menuVoiceOff = !_vm->_soundMan->_voiceOffFl ? 7 : 8;
|
||||
_vm->_globals->_menuSoundOff = !_vm->_soundMan->_soundOffFl ? 7 : 8;
|
||||
_vm->_globals->_menuMusicOff = !_vm->_soundMan->_musicOffFl ? 7 : 8;
|
||||
|
||||
_vm->_globals->_menuDisplayType = 9;
|
||||
|
||||
switch (_vm->_graphicsMan->_scrollSpeed) {
|
||||
case 1:
|
||||
_vm->_globals->_menuScrollSpeed = 12;
|
||||
break;
|
||||
case 2:
|
||||
_vm->_globals->_menuScrollSpeed = 13;
|
||||
break;
|
||||
case 4:
|
||||
_vm->_globals->_menuScrollSpeed = 14;
|
||||
break;
|
||||
case 8:
|
||||
_vm->_globals->_menuScrollSpeed = 15;
|
||||
break;
|
||||
case 16:
|
||||
_vm->_globals->_menuScrollSpeed = 16;
|
||||
break;
|
||||
case 32:
|
||||
_vm->_globals->_menuScrollSpeed = 17;
|
||||
break;
|
||||
case 48:
|
||||
_vm->_globals->_menuScrollSpeed = 18;
|
||||
break;
|
||||
case 64:
|
||||
_vm->_globals->_menuScrollSpeed = 19;
|
||||
break;
|
||||
case 128:
|
||||
_vm->_globals->_menuScrollSpeed = 20;
|
||||
break;
|
||||
case 160:
|
||||
_vm->_globals->_menuScrollSpeed = 21;
|
||||
break;
|
||||
case 320:
|
||||
_vm->_globals->_menuScrollSpeed = 22;
|
||||
break;
|
||||
case 640:
|
||||
_vm->_globals->_menuScrollSpeed = 23;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
} while (!doneFlag);
|
||||
|
||||
_vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, scrollOffset + 164,
|
||||
107, 335, 215, _vm->_graphicsMan->_frontBuffer, scrollOffset + 164, 107);
|
||||
_vm->_graphicsMan->addDirtyRect(scrollOffset + 164, 107, scrollOffset + 498, 320);
|
||||
|
||||
_vm->_globals->_optionDialogSpr = _vm->_globals->freeMemory(_vm->_globals->_optionDialogSpr);
|
||||
_vm->_globals->_optionDialogFl = false;
|
||||
}
|
||||
|
||||
void DialogsManager::showInventory() {
|
||||
if (_removeInventFl || _inventDisplayedFl || _vm->_globals->_disableInventFl)
|
||||
return;
|
||||
|
||||
_vm->_graphicsMan->_scrollStatus = 1;
|
||||
_vm->_objectsMan->_eraseVisibleCounter = 4;
|
||||
_vm->_objectsMan->_visibleFl = false;
|
||||
for (int i = 0; i <= 1; i++) {
|
||||
inventAnim();
|
||||
_vm->_events->getMouseX();
|
||||
_vm->_events->getMouseY();
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
}
|
||||
_inventWin1 = nullptr;
|
||||
|
||||
bool loopFl;
|
||||
do {
|
||||
loopFl = false;
|
||||
_vm->_events->_curMouseButton = 0;
|
||||
_vm->_events->_mouseButton = 0;
|
||||
_vm->_globals->_disableInventFl = true;
|
||||
_vm->_graphicsMan->setColorPercentage2(251, 100, 100, 100);
|
||||
|
||||
Common::Path filename;
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
|
||||
filename = "INVENT.SPR";
|
||||
else {
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_EN:
|
||||
filename = "INVENTAN.SPR";
|
||||
break;
|
||||
case LANG_FR:
|
||||
filename = "INVENTFR.SPR";
|
||||
break;
|
||||
case LANG_SP:
|
||||
filename = "INVENTES.SPR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Common::File f;
|
||||
if (!f.open(filename))
|
||||
error("Error opening file - %s", filename.toString().c_str());
|
||||
|
||||
size_t filesize = f.size();
|
||||
_inventWin1 = _vm->_globals->allocMemory(filesize);
|
||||
_vm->_fileIO->readStream(f, _inventWin1, filesize);
|
||||
f.close();
|
||||
|
||||
_inventBuf2 = _vm->_fileIO->loadFile("INVENT2.SPR");
|
||||
|
||||
_inventX = _vm->_graphicsMan->_scrollOffset + 152;
|
||||
_inventY = 114;
|
||||
_inventWidth = _vm->_objectsMan->getWidth(_inventWin1, 0);
|
||||
_inventHeight = _vm->_objectsMan->getHeight(_inventWin1, 0);
|
||||
|
||||
_vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer, _inventWin1, _inventX + 300, 414, 0, 0, 0, false);
|
||||
int curPosY = 0;
|
||||
int inventCount = 0;
|
||||
for (int inventLine = 1; inventLine <= 5; inventLine++) {
|
||||
int curPosX = 0;
|
||||
for (int inventCol = 1; inventCol <= 6; inventCol++) {
|
||||
++inventCount;
|
||||
int inventIdx = _vm->_globals->_inventory[inventCount];
|
||||
// The last two zones are not reserved for the inventory: Options and Save/Load
|
||||
if (inventIdx && inventCount <= 29) {
|
||||
byte *obj = _vm->_objectsMan->loadObjectFromFile(inventIdx, false);
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, obj, _inventX + curPosX + 6,
|
||||
curPosY + 120, _vm->_objectsMan->getObjectWidth(), _vm->_objectsMan->getObjectHeight());
|
||||
_vm->_globals->freeMemory(obj);
|
||||
}
|
||||
curPosX += 54;
|
||||
};
|
||||
curPosY += 38;
|
||||
}
|
||||
_vm->_graphicsMan->copySurfaceRect(_vm->_graphicsMan->_frontBuffer, _inventWin1, _inventX, _inventY, _inventWidth, _inventHeight);
|
||||
_vm->_events->_curMouseButton = 0;
|
||||
int newInventoryItem = 0;
|
||||
|
||||
// Main loop to select an inventory item
|
||||
while (!_vm->shouldQuit()) {
|
||||
// Turn on drawing the inventory dialog in the event manager
|
||||
_inventDisplayedFl = true;
|
||||
|
||||
int mousePosX = _vm->_events->getMouseX();
|
||||
int mousePosY = _vm->_events->getMouseY();
|
||||
int mouseButton = _vm->_events->getMouseButton();
|
||||
int oldInventoryItem = newInventoryItem;
|
||||
newInventoryItem = _vm->_linesMan->checkInventoryHotspots(mousePosX, mousePosY);
|
||||
if (newInventoryItem != oldInventoryItem)
|
||||
_vm->_objectsMan->initBorder(newInventoryItem);
|
||||
int cursorId = _vm->_events->_mouseCursorId;
|
||||
if (cursorId != 1 && cursorId != 2 && cursorId != 3 && cursorId != 16) {
|
||||
if (mouseButton == 2) {
|
||||
_vm->_objectsMan->nextObjectIcon(newInventoryItem);
|
||||
cursorId = _vm->_events->_mouseCursorId;
|
||||
if (cursorId != 23)
|
||||
_vm->_events->changeMouseCursor(cursorId);
|
||||
}
|
||||
}
|
||||
cursorId = _vm->_events->_mouseCursorId;
|
||||
if (mouseButton == 1) {
|
||||
if (cursorId == 1 || cursorId == 2 || cursorId == 3 || cursorId == 16 || !cursorId)
|
||||
break;
|
||||
_vm->_objectsMan->takeInventoryObject(_vm->_globals->_inventory[newInventoryItem]);
|
||||
if (_vm->_events->_mouseCursorId == 8)
|
||||
break;
|
||||
|
||||
_vm->_script->_tempObjectFl = true;
|
||||
_vm->_globals->_saveData->_data[svLastObjectIndex] = _vm->_objectsMan->_curObjectIndex;
|
||||
_vm->_globals->_saveData->_data[svLastInventoryItem] = _vm->_globals->_inventory[newInventoryItem];
|
||||
_vm->_globals->_saveData->_data[svLastInvMouseCursor] = _vm->_events->_mouseCursorId;
|
||||
_vm->_objectsMan->loadObjectIniFile();
|
||||
_vm->_script->_tempObjectFl = false;
|
||||
|
||||
if (_vm->_soundMan->_voiceOffFl) {
|
||||
do {
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
} while (!_vm->_globals->_exitId && _vm->_events->getMouseButton() != 1);
|
||||
_vm->_fontMan->hideText(9);
|
||||
}
|
||||
if (_vm->_globals->_exitId) {
|
||||
if (_vm->_globals->_exitId == 2) {
|
||||
_vm->_globals->_exitId = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_globals->_exitId = 0;
|
||||
_inventBuf2 = _vm->_globals->freeMemory(_inventBuf2);
|
||||
_inventWin1 = _vm->_globals->freeMemory(_inventWin1);
|
||||
loopFl = true;
|
||||
break;
|
||||
} else
|
||||
_inventDisplayedFl = true;
|
||||
}
|
||||
if (_removeInventFl)
|
||||
break;
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
if (_vm->_globals->_screenId >= 35 && _vm->_globals->_screenId <= 40)
|
||||
_vm->_objectsMan->handleSpecialGames();
|
||||
}
|
||||
} while (loopFl);
|
||||
|
||||
_vm->_fontMan->hideText(9);
|
||||
if (_inventDisplayedFl) {
|
||||
_inventDisplayedFl = false;
|
||||
_vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, _inventX, 114, _inventWidth, _inventHeight, _vm->_graphicsMan->_frontBuffer, _inventX, 114);
|
||||
_vm->_graphicsMan->addDirtyRect(_inventX, 114, _inventX + _inventWidth, _inventWidth + 114);
|
||||
_vm->_objectsMan->_refreshBobMode10Fl = true;
|
||||
}
|
||||
|
||||
_inventWin1 = _vm->_globals->freeMemory(_inventWin1);
|
||||
_inventBuf2 = _vm->_globals->freeMemory(_inventBuf2);
|
||||
|
||||
int cursorId = _vm->_events->_mouseCursorId;
|
||||
if (cursorId == 1)
|
||||
showOptionsDialog();
|
||||
else if (cursorId == 3)
|
||||
showLoadGame();
|
||||
else if (cursorId == 2)
|
||||
showSaveGame();
|
||||
|
||||
_vm->_events->_mouseCursorId = 4;
|
||||
_vm->_events->changeMouseCursor(4);
|
||||
_vm->_objectsMan->_oldBorderPos = Common::Point(0, 0);
|
||||
_vm->_objectsMan->_borderPos = Common::Point(0, 0);
|
||||
_vm->_globals->_disableInventFl = false;
|
||||
_vm->_graphicsMan->_scrollStatus = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inventory Animations
|
||||
*/
|
||||
void DialogsManager::inventAnim() {
|
||||
if (_vm->_globals->_disableInventFl)
|
||||
return;
|
||||
|
||||
if (_vm->_objectsMan->_eraseVisibleCounter && !_vm->_objectsMan->_visibleFl) {
|
||||
_vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, _oldInventX, 27, 48, 38,
|
||||
_vm->_graphicsMan->_frontBuffer, _oldInventX, 27);
|
||||
_vm->_graphicsMan->addDirtyRect(_oldInventX, 27, _oldInventX + 48, 65);
|
||||
--_vm->_objectsMan->_eraseVisibleCounter;
|
||||
}
|
||||
|
||||
if (_vm->_objectsMan->_visibleFl) {
|
||||
if (_oldInventX <= 1)
|
||||
_oldInventX = 2;
|
||||
_vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, _oldInventX, 27, 48, 38,
|
||||
_vm->_graphicsMan->_frontBuffer, _oldInventX, 27);
|
||||
|
||||
_vm->_graphicsMan->addDirtyRect(_oldInventX, 27, _oldInventX + 48, 65);
|
||||
int newOffset = _vm->_graphicsMan->_scrollOffset + 2;
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _inventoryIcons, newOffset + 300, 327, 0);
|
||||
_vm->_graphicsMan->addDirtyRect(newOffset, 27, newOffset + 45, 62);
|
||||
_oldInventX = newOffset;
|
||||
}
|
||||
|
||||
if (_vm->_globals->_saveData->_data[svField357] == 1) {
|
||||
if (_vm->_globals->_saveData->_data[svField353] == 1)
|
||||
_vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_headSprites, 832, 325, 0, 0, 0, false);
|
||||
if (_vm->_globals->_saveData->_data[svField355] == 1)
|
||||
_vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_headSprites, 866, 325, 1, 0, 0, false);
|
||||
_vm->_graphicsMan->addDirtyRect(532, 25, 560, 60);
|
||||
_vm->_graphicsMan->addDirtyRect(566, 25, 594, 60);
|
||||
}
|
||||
if (_vm->_globals->_saveData->_data[svField356] == 1) {
|
||||
_vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_headSprites, 832, 325, 0, 0, 0, false);
|
||||
_vm->_graphicsMan->addDirtyRect(532, 25, 560, 60);
|
||||
}
|
||||
|
||||
if (_vm->_globals->_saveData->_data[svField354] == 1) {
|
||||
_vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_headSprites, 832, 325, 0, 0, 0, false);
|
||||
_vm->_graphicsMan->addDirtyRect(532, 25, 560, 60);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test dialog opening
|
||||
*/
|
||||
void DialogsManager::testDialogOpening() {
|
||||
if (_vm->_globals->_cityMapEnabledFl)
|
||||
_vm->_events->_gameKey = KEY_NONE;
|
||||
|
||||
if ((_vm->_events->_gameKey == KEY_NONE) || _inventFl)
|
||||
return;
|
||||
|
||||
DIALOG_KEY key = _vm->_events->_gameKey;
|
||||
_vm->_events->_gameKey = KEY_NONE;
|
||||
_inventFl = true;
|
||||
|
||||
switch (key) {
|
||||
case KEY_INVENTORY:
|
||||
showInventory();
|
||||
break;
|
||||
case KEY_OPTIONS:
|
||||
_vm->_graphicsMan->_scrollStatus = 1;
|
||||
showOptionsDialog();
|
||||
_vm->_graphicsMan->_scrollStatus = 0;
|
||||
break;
|
||||
case KEY_LOAD:
|
||||
_vm->_graphicsMan->_scrollStatus = 1;
|
||||
showLoadGame();
|
||||
_vm->_graphicsMan->_scrollStatus = 0;
|
||||
break;
|
||||
case KEY_SAVE:
|
||||
_vm->_graphicsMan->_scrollStatus = 1;
|
||||
showSaveGame();
|
||||
_vm->_graphicsMan->_scrollStatus = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_inventFl = false;
|
||||
_vm->_events->_gameKey = KEY_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Game dialog
|
||||
*/
|
||||
void DialogsManager::showLoadGame() {
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
showSaveLoad(MODE_LOAD);
|
||||
|
||||
int slotNumber;
|
||||
do {
|
||||
slotNumber = searchSavegames();
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
} while (!_vm->shouldQuit() && (!slotNumber || _vm->_events->getMouseButton() != 1));
|
||||
_vm->_objectsMan->_saveLoadFl = false;
|
||||
int16 startPosX = _vm->_events->_startPos.x + 183;
|
||||
_vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, startPosX, 60, 274, 353, _vm->_graphicsMan->_frontBuffer, startPosX, 60);
|
||||
_vm->_graphicsMan->addDirtyRect(startPosX, 60, startPosX + 274, 413);
|
||||
_vm->_objectsMan->_refreshBobMode10Fl = true;
|
||||
_vm->_objectsMan->_saveLoadSprite = _vm->_globals->freeMemory(_vm->_objectsMan->_saveLoadSprite);
|
||||
_vm->_objectsMan->_saveLoadSprite2 = _vm->_globals->freeMemory(_vm->_objectsMan->_saveLoadSprite2);
|
||||
_vm->_objectsMan->_saveLoadX = 0;
|
||||
_vm->_objectsMan->_saveLoadY = 0;
|
||||
|
||||
if (slotNumber != 7) {
|
||||
_vm->_saveLoad->loadGame(slotNumber);
|
||||
}
|
||||
|
||||
_vm->_objectsMan->changeObject(14);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Game dialog
|
||||
*/
|
||||
void DialogsManager::showSaveGame() {
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
|
||||
showSaveLoad(MODE_SAVE);
|
||||
int slotNumber;
|
||||
do {
|
||||
slotNumber = searchSavegames();
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
} while (!_vm->shouldQuit() && (!slotNumber || _vm->_events->getMouseButton() != 1));
|
||||
|
||||
_vm->_objectsMan->_saveLoadFl = false;
|
||||
int16 startPosX = _vm->_events->_startPos.x + 183;
|
||||
_vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, startPosX, 60, 274, 353, _vm->_graphicsMan->_frontBuffer, startPosX, 60);
|
||||
_vm->_graphicsMan->addDirtyRect(startPosX, 60, startPosX + 274, 413);
|
||||
_vm->_objectsMan->_refreshBobMode10Fl = true;
|
||||
_vm->_objectsMan->_saveLoadSprite = _vm->_globals->freeMemory(_vm->_objectsMan->_saveLoadSprite);
|
||||
_vm->_objectsMan->_saveLoadSprite2 = _vm->_globals->freeMemory(_vm->_objectsMan->_saveLoadSprite2);
|
||||
_vm->_objectsMan->_saveLoadX = 0;
|
||||
_vm->_objectsMan->_saveLoadY = 0;
|
||||
|
||||
if (slotNumber != 7) {
|
||||
// Since the original GUI doesn't support save names, use a default name
|
||||
Common::String saveName = Common::String::format("Save #%d", slotNumber);
|
||||
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
// Save the game
|
||||
_vm->_saveLoad->saveGame(slotNumber, saveName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load/Save dialog
|
||||
*/
|
||||
void DialogsManager::showSaveLoad(SaveLoadMode mode) {
|
||||
Common::Path filename;
|
||||
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
|
||||
filename = "SAVE.SPR";
|
||||
else {
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_EN:
|
||||
filename = "SAVEAN.SPR";
|
||||
break;
|
||||
case LANG_FR:
|
||||
filename = "SAVEFR.SPR";
|
||||
break;
|
||||
case LANG_SP:
|
||||
filename = "SAVEES.SPR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_objectsMan->_saveLoadSprite = _vm->_objectsMan->loadSprite(filename);
|
||||
_vm->_objectsMan->_saveLoadSprite2 = _vm->_objectsMan->loadSprite("SAVE2.SPR");
|
||||
int16 startPosX = _vm->_events->_startPos.x;
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_saveLoadSprite, startPosX + 483, 360, 0);
|
||||
|
||||
if (_vm->_globals->_language == LANG_FR) {
|
||||
if (mode == MODE_SAVE)
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_saveLoadSprite, startPosX + 525, 375, 1);
|
||||
else if (mode == MODE_LOAD)
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_saveLoadSprite, startPosX + 515, 375, 2);
|
||||
} else {
|
||||
if (mode == MODE_SAVE)
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_saveLoadSprite, startPosX + 535, 372, 1);
|
||||
else if (mode == MODE_LOAD)
|
||||
_vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_saveLoadSprite, startPosX + 539, 372, 2);
|
||||
}
|
||||
|
||||
for (int slotNumber = 1; slotNumber <= 6; ++slotNumber) {
|
||||
hopkinsSavegameHeader header;
|
||||
if (_vm->_saveLoad->readSavegameHeader(slotNumber, header, false)) {
|
||||
Graphics::Surface thumb8;
|
||||
_vm->_saveLoad->convertThumb16To8(header._thumbnail, &thumb8);
|
||||
|
||||
byte *thumb = (byte *)thumb8.getPixels();
|
||||
|
||||
int16 startPosX_ = _vm->_events->_startPos.x;
|
||||
switch (slotNumber) {
|
||||
case 1:
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, thumb, startPosX_ + 190, 112, 128, 87);
|
||||
break;
|
||||
case 2:
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, thumb, startPosX_ + 323, 112, 128, 87);
|
||||
break;
|
||||
case 3:
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, thumb, startPosX_ + 190, 203, 128, 87);
|
||||
break;
|
||||
case 4:
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, thumb, startPosX_ + 323, 203, 128, 87);
|
||||
break;
|
||||
case 5:
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, thumb, startPosX_ + 190, 294, 128, 87);
|
||||
break;
|
||||
case 6:
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, thumb, startPosX_ + 323, 294, 128, 87);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
thumb8.free();
|
||||
header._thumbnail->free();
|
||||
delete header._thumbnail;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphicsMan->copySurfaceRect(_vm->_graphicsMan->_frontBuffer, _vm->_objectsMan->_saveLoadSprite, _vm->_events->_startPos.x + 183, 60, 274, 353);
|
||||
_vm->_objectsMan->_saveLoadFl = true;
|
||||
_vm->_objectsMan->_saveLoadX = 0;
|
||||
_vm->_objectsMan->_saveLoadY = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search savegames
|
||||
*/
|
||||
int DialogsManager::searchSavegames() {
|
||||
int xp = _vm->_events->getMouseX();
|
||||
int yp = _vm->_events->getMouseY();
|
||||
|
||||
int16 startPosX = _vm->_graphicsMan->_scrollOffset = _vm->_events->_startPos.x;
|
||||
|
||||
int slotNumber = 0;
|
||||
if (yp >= 112 && yp <= 198) {
|
||||
if (xp > startPosX + 189 && xp < startPosX + 318) {
|
||||
slotNumber = 1;
|
||||
_vm->_objectsMan->_saveLoadX = 189;
|
||||
_vm->_objectsMan->_saveLoadY = 111;
|
||||
} else if (xp > startPosX + 322 && xp < startPosX + 452) {
|
||||
slotNumber = 2;
|
||||
_vm->_objectsMan->_saveLoadX = 322;
|
||||
_vm->_objectsMan->_saveLoadY = 111;
|
||||
}
|
||||
} else if (yp >= 203 && yp <= 289) {
|
||||
if (xp > startPosX + 189 && xp < startPosX + 318) {
|
||||
slotNumber = 3;
|
||||
_vm->_objectsMan->_saveLoadX = 189;
|
||||
_vm->_objectsMan->_saveLoadY = 202;
|
||||
} else if (xp > startPosX + 322 && xp < startPosX + 452) {
|
||||
slotNumber = 4;
|
||||
_vm->_objectsMan->_saveLoadX = 322;
|
||||
_vm->_objectsMan->_saveLoadY = 202;
|
||||
}
|
||||
} else if (yp >= 294 && yp <= 380) {
|
||||
if (xp > startPosX + 189 && xp < startPosX + 318) {
|
||||
slotNumber = 5;
|
||||
_vm->_objectsMan->_saveLoadX = 189;
|
||||
_vm->_objectsMan->_saveLoadY = 293;
|
||||
} else if (xp > startPosX + 322 && xp < startPosX + 452) {
|
||||
slotNumber = 6;
|
||||
_vm->_objectsMan->_saveLoadX = 322;
|
||||
_vm->_objectsMan->_saveLoadY = 293;
|
||||
}
|
||||
} else if (yp >= 388 && yp <= 404 && xp > startPosX + 273 && xp < startPosX + 355) {
|
||||
slotNumber = 7;
|
||||
_vm->_objectsMan->_saveLoadX = 0;
|
||||
_vm->_objectsMan->_saveLoadY = 0;
|
||||
} else {
|
||||
slotNumber = 0;
|
||||
_vm->_objectsMan->_saveLoadX = 0;
|
||||
_vm->_objectsMan->_saveLoadY = 0;
|
||||
}
|
||||
|
||||
return slotNumber;
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
76
engines/hopkins/dialogs.h
Normal file
76
engines/hopkins/dialogs.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HOPKINS_DIALOGS_H
|
||||
#define HOPKINS_DIALOGS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "common/error.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
enum SaveLoadMode { MODE_SAVE = 1, MODE_LOAD = 2 };
|
||||
|
||||
/**
|
||||
* Class for manging game dialogs
|
||||
*/
|
||||
class DialogsManager {
|
||||
private:
|
||||
byte *_inventWin1;
|
||||
byte *_inventBuf2;
|
||||
byte *_inventoryIcons;
|
||||
bool _inventDisplayedFl;
|
||||
bool _removeInventFl;
|
||||
int _inventX, _inventY;
|
||||
int _inventWidth, _inventHeight;
|
||||
int _oldInventX;
|
||||
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
void showSaveLoad(SaveLoadMode mode);
|
||||
int searchSavegames();
|
||||
public:
|
||||
bool _inventFl;
|
||||
|
||||
DialogsManager(HopkinsEngine *vm);
|
||||
~DialogsManager();
|
||||
void inventAnim();
|
||||
void showInventory();
|
||||
void showLoadGame();
|
||||
void showSaveGame();
|
||||
void showOptionsDialog();
|
||||
void testDialogOpening();
|
||||
void clearAll();
|
||||
|
||||
void drawInvent(Common::Point oldBorder, int oldBorderSpriteIndex, Common::Point newBorder, int newBorderSpriteIndex);
|
||||
void loadIcons();
|
||||
|
||||
void disableInvent() { _removeInventFl = true; }
|
||||
void enableInvent() { _removeInventFl = false; }
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_MENU_H */
|
||||
542
engines/hopkins/events.cpp
Normal file
542
engines/hopkins/events.cpp
Normal file
@@ -0,0 +1,542 @@
|
||||
/* 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 "hopkins/events.h"
|
||||
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
#include "hopkins/sound.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "graphics/cursorman.h"
|
||||
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
EventsManager::EventsManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
_mouseFl = false;
|
||||
_mouseLinuxFl = false;
|
||||
_mouseSizeX = _mouseSizeY = 0;
|
||||
_mouseOffset.x = _mouseOffset.y = 0;
|
||||
_startPos.x = _startPos.y = 0;
|
||||
_breakoutFl = false;
|
||||
_mouseSpriteId = 0;
|
||||
_curMouseButton = 0;
|
||||
_mouseButton = 0;
|
||||
_mouseCursor = nullptr;
|
||||
_gameCounter = 0;
|
||||
_rateCounter = 0;
|
||||
_escKeyFl = false;
|
||||
_gameKey = KEY_NONE;
|
||||
_mouseCursorId = 0;
|
||||
_oldIconId = 0;
|
||||
_objectBuf = nullptr;
|
||||
|
||||
Common::fill(&_keyState[0], &_keyState[256], false);
|
||||
_priorCounterTime = _priorFrameTime = g_system->getMillis();
|
||||
}
|
||||
|
||||
EventsManager::~EventsManager() {
|
||||
_vm->_globals->freeMemory(_objectBuf);
|
||||
_vm->_globals->freeMemory(_mouseCursor);
|
||||
}
|
||||
|
||||
void EventsManager::clearAll() {
|
||||
_vm->_globals->freeMemory(_objectBuf);
|
||||
_objectBuf = _vm->_globals->allocMemory(2500);
|
||||
}
|
||||
|
||||
void EventsManager::initMouseData() {
|
||||
if (_vm->getPlatform() == Common::kPlatformLinux)
|
||||
_mouseLinuxFl = true;
|
||||
else
|
||||
_mouseLinuxFl = false;
|
||||
|
||||
if (_mouseLinuxFl) {
|
||||
_mouseSizeX = 52;
|
||||
_mouseSizeY = 32;
|
||||
} else {
|
||||
_mouseSizeX = 34;
|
||||
_mouseSizeY = 20;
|
||||
}
|
||||
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_EN:
|
||||
if (!_mouseLinuxFl)
|
||||
_mouseCursor = _vm->_fileIO->loadFile("SOUAN.SPR");
|
||||
else
|
||||
_mouseCursor = _vm->_fileIO->loadFile("LSOUAN.SPR");
|
||||
break;
|
||||
case LANG_FR:
|
||||
if (!_mouseLinuxFl)
|
||||
_mouseCursor = _vm->_fileIO->loadFile("SOUFR.SPR");
|
||||
else
|
||||
_mouseCursor = _vm->_fileIO->loadFile("LSOUFR.SPR");
|
||||
break;
|
||||
case LANG_SP:
|
||||
_mouseCursor = _vm->_fileIO->loadFile("SOUES.SPR");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse On
|
||||
void EventsManager::setMouseOn() {
|
||||
_mouseFl = true;
|
||||
|
||||
if (_mouseLinuxFl) {
|
||||
_mouseSizeX = 52;
|
||||
_mouseSizeY = 32;
|
||||
} else {
|
||||
_mouseSizeX = 34;
|
||||
_mouseSizeY = 20;
|
||||
}
|
||||
|
||||
_mouseOffset.x = 0;
|
||||
_mouseOffset.y = 0;
|
||||
|
||||
if (!_breakoutFl)
|
||||
setMouseXY(300, 200);
|
||||
else
|
||||
setMouseXY(150, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Mouse position
|
||||
*/
|
||||
void EventsManager::setMouseXY(Common::Point pos) {
|
||||
g_system->warpMouse(pos.x, pos.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Mouse position
|
||||
*/
|
||||
void EventsManager::setMouseXY(int xp, int yp) {
|
||||
g_system->warpMouse(xp, yp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Mouse X
|
||||
*/
|
||||
int EventsManager::getMouseX() {
|
||||
_mousePos.x = _startPos.x + g_system->getEventManager()->getMousePos().x;
|
||||
_mousePos.y = g_system->getEventManager()->getMousePos().y;
|
||||
|
||||
return _mousePos.x + _mouseOffset.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Mouse Y
|
||||
*/
|
||||
int EventsManager::getMouseY() {
|
||||
_mousePos.x = _startPos.x + g_system->getEventManager()->getMousePos().x;
|
||||
_mousePos.y = g_system->getEventManager()->getMousePos().y;
|
||||
|
||||
return _mousePos.y + _mouseOffset.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Mouse Button
|
||||
*/
|
||||
int EventsManager::getMouseButton() {
|
||||
refreshEvents();
|
||||
return _curMouseButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouse Off
|
||||
*/
|
||||
void EventsManager::mouseOff() {
|
||||
_mouseFl = false;
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouse On
|
||||
*/
|
||||
void EventsManager::mouseOn() {
|
||||
setMouseOn();
|
||||
_mouseFl = true;
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Mouse Cursor
|
||||
*/
|
||||
void EventsManager::changeMouseCursor(int id) {
|
||||
int cursorId = id;
|
||||
|
||||
if (_mouseCursorId == 23)
|
||||
return;
|
||||
|
||||
if (id == 4 && _mouseCursorId == 4 && _vm->_globals->_freezeCharacterFl)
|
||||
cursorId = 0;
|
||||
if (cursorId == 25)
|
||||
cursorId = 5;
|
||||
|
||||
if (_oldIconId != cursorId || !cursorId) {
|
||||
_oldIconId = cursorId;
|
||||
_mouseSpriteId = cursorId;
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Events
|
||||
*/
|
||||
void EventsManager::refreshEvents() {
|
||||
_vm->_soundMan->checkSounds();
|
||||
|
||||
pollEvents();
|
||||
}
|
||||
|
||||
void EventsManager::checkForNextFrameCounter() {
|
||||
int32 delayAmount = 10 - (g_system->getMillis() - _priorCounterTime);
|
||||
if (delayAmount > 0)
|
||||
_vm->_system->delayMillis(delayAmount);
|
||||
|
||||
// Check for whether to increment the game counter
|
||||
uint32 milli = g_system->getMillis();
|
||||
while ((milli - _priorCounterTime) >= 10) {
|
||||
_priorCounterTime += 10;
|
||||
_rateCounter += 3;
|
||||
}
|
||||
|
||||
// Check for next game frame
|
||||
if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
|
||||
++_gameCounter;
|
||||
_priorFrameTime = milli;
|
||||
_vm->_graphicsMan->updateScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::delay(int totalMilli) {
|
||||
uint32 delayEnd = g_system->getMillis() + totalMilli;
|
||||
|
||||
while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) {
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::pollEvents() {
|
||||
checkForNextFrameCounter();
|
||||
|
||||
Common::Event event;
|
||||
while (g_system->getEventManager()->pollEvent(event)) {
|
||||
// Handle keypress
|
||||
switch (event.type) {
|
||||
case Common::EVENT_QUIT:
|
||||
case Common::EVENT_RETURN_TO_LAUNCHER:
|
||||
return;
|
||||
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
|
||||
handleKey(event);
|
||||
return;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
_keyState[(byte)toupper(event.kbd.ascii)] = true;
|
||||
return;
|
||||
case Common::EVENT_KEYUP:
|
||||
_keyState[(byte)toupper(event.kbd.ascii)] = false;
|
||||
return;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
_mouseButton = 1;
|
||||
return;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
_mouseButton = 2;
|
||||
return;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
_mouseButton = 0;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (char chr = 'A'; chr <= 'Z'; chr++)
|
||||
_keyState[(byte)chr] = false;
|
||||
|
||||
for (char chr = '0'; chr <= '9'; chr++)
|
||||
_keyState[(byte)chr] = false;
|
||||
}
|
||||
|
||||
void EventsManager::handleKey(const Common::Event &event) {
|
||||
_escKeyFl = (event.customType == kActionEscape);
|
||||
|
||||
if (event.customType == kActionInventory)
|
||||
_gameKey = KEY_INVENTORY;
|
||||
else if (event.customType == kActionSave)
|
||||
_gameKey = KEY_SAVE;
|
||||
else if (event.customType == kActionLoad)
|
||||
_gameKey = KEY_LOAD;
|
||||
else if (event.customType == kActionOptions)
|
||||
_gameKey = KEY_OPTIONS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a keypress, ignoring mouse events
|
||||
* @return Keypress, or -1 if game quit was requested
|
||||
*/
|
||||
int EventsManager::waitKeyPress() {
|
||||
|
||||
Common::Keymapper *keymapper = _vm->getEventManager()->getKeymapper();
|
||||
keymapper->getKeymap("game-shortcuts")->setEnabled(false);
|
||||
|
||||
char foundChar = '\0';
|
||||
|
||||
while (!foundChar) {
|
||||
if (_vm->shouldQuit())
|
||||
return -1;
|
||||
|
||||
for (char ch = 'A'; ch <= 'Z'; ++ch) {
|
||||
if (_keyState[(byte)ch]) {
|
||||
foundChar = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (char ch = '0'; ch <= '9'; ++ch) {
|
||||
if (_keyState[(byte)ch]) {
|
||||
foundChar = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_keyState[(byte)'.'])
|
||||
foundChar = '.';
|
||||
else if (_keyState[8])
|
||||
// BACKSPACE
|
||||
foundChar = 8;
|
||||
else if (_keyState[13])
|
||||
// ENTER
|
||||
foundChar = 13;
|
||||
else if (_keyState[(byte)' '])
|
||||
foundChar = ' ';
|
||||
|
||||
refreshScreenAndEvents();
|
||||
}
|
||||
|
||||
// Wait for keypress release
|
||||
while (_keyState[(byte)foundChar] && !_vm->shouldQuit()) {
|
||||
refreshScreenAndEvents();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
keymapper->getKeymap("game-shortcuts")->setEnabled(true);
|
||||
|
||||
// Return character
|
||||
return foundChar;
|
||||
}
|
||||
|
||||
void EventsManager::refreshScreenAndEvents() {
|
||||
int bottom = 0;
|
||||
int right = 0;
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
int xp = 0;
|
||||
int yp = 0;
|
||||
|
||||
if (_mouseFl) {
|
||||
int mouseWidth = 20;
|
||||
if (!_mouseLinuxFl)
|
||||
mouseWidth = 10;
|
||||
int mouseHeight = 20;
|
||||
if (!_mouseLinuxFl)
|
||||
mouseHeight = 15;
|
||||
xp = _mousePos.x - mouseWidth;
|
||||
yp = _mousePos.y;
|
||||
width = _mouseSizeX;
|
||||
height = _mouseSizeY;
|
||||
if (_mouseCursorId == 23) {
|
||||
width = _vm->_objectsMan->getObjectWidth();
|
||||
height = _vm->_objectsMan->getObjectHeight();
|
||||
} else {
|
||||
if (_breakoutFl) {
|
||||
if (xp < _vm->_graphicsMan->_minX)
|
||||
xp = _vm->_graphicsMan->_minX;
|
||||
if (_mousePos.y < _vm->_graphicsMan->_minY)
|
||||
yp = _vm->_graphicsMan->_minY;
|
||||
if (_mouseSizeX + xp >= _vm->_graphicsMan->_maxX)
|
||||
width = _mouseSizeX - (_mouseSizeX + xp - _vm->_graphicsMan->_maxX);
|
||||
if (yp + _mouseSizeY >= _vm->_graphicsMan->_maxY)
|
||||
height = _vm->_graphicsMan->_maxY - yp;
|
||||
} else {
|
||||
if (xp < _vm->_graphicsMan->_minX)
|
||||
xp = _vm->_graphicsMan->_minX - mouseWidth;
|
||||
mouseHeight = (int16)mouseHeight;
|
||||
if (_mousePos.y < _vm->_graphicsMan->_minY - mouseHeight)
|
||||
yp = _vm->_graphicsMan->_minY - mouseHeight;
|
||||
if (_mouseSizeX + xp >= _vm->_graphicsMan->_maxX)
|
||||
width = _mouseSizeX - (_mouseSizeX + xp - _vm->_graphicsMan->_maxX - mouseWidth);
|
||||
if (yp + _mouseSizeY >= mouseHeight + _vm->_graphicsMan->_maxY)
|
||||
height = _vm->_graphicsMan->_maxY - mouseHeight - yp;
|
||||
}
|
||||
right = xp + width;
|
||||
bottom = yp + height;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_vm->_globals->_linuxEndDemoFl)
|
||||
_vm->_objectsMan->displaySprite();
|
||||
if (!_mouseFl) {
|
||||
updateCursor();
|
||||
} else if (_mouseCursorId == 23) {
|
||||
if (yp < _vm->_graphicsMan->_maxY && xp < _vm->_graphicsMan->_maxX) {
|
||||
if (width + xp > _vm->_graphicsMan->_maxX)
|
||||
width = _vm->_graphicsMan->_maxX - xp;
|
||||
if (yp + height > _vm->_graphicsMan->_maxY)
|
||||
height = _vm->_graphicsMan->_maxY - yp;
|
||||
if (width > 1 && height > 1) {
|
||||
updateCursor();
|
||||
}
|
||||
}
|
||||
} else if (yp < _vm->_graphicsMan->_maxY && xp < _vm->_graphicsMan->_maxX && width > 1 && height > 1) {
|
||||
updateCursor();
|
||||
_vm->_graphicsMan->addDirtyRect(xp, yp, right, bottom);
|
||||
}
|
||||
|
||||
_vm->_globals->_speed = 2;
|
||||
bool externalLoopFl = false;
|
||||
do {
|
||||
while (!_vm->shouldQuit()) {
|
||||
checkForNextFrameCounter();
|
||||
bool innerLoopFl = false;
|
||||
|
||||
while (!_vm->shouldQuit() && (_breakoutFl || _vm->_globals->_eventMode != EVENTMODE_IGNORE)) {
|
||||
checkForNextFrameCounter();
|
||||
|
||||
if (!_breakoutFl) {
|
||||
innerLoopFl = true;
|
||||
break;
|
||||
}
|
||||
if (_rateCounter > 1) {
|
||||
externalLoopFl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (innerLoopFl || _vm->_globals->_speed != 2)
|
||||
break;
|
||||
if (externalLoopFl ||_rateCounter > 9) {
|
||||
externalLoopFl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (externalLoopFl)
|
||||
break;
|
||||
} while (!_vm->shouldQuit() && _vm->_globals->_eventMode == EVENTMODE_CREDITS && _rateCounter <= 15);
|
||||
_vm->_globals->_speed = 2;
|
||||
_rateCounter = 0;
|
||||
if (!_vm->_graphicsMan->_largeScreenFl || _vm->_graphicsMan->_scrollStatus == 1) {
|
||||
_vm->_graphicsMan->displayDirtyRects();
|
||||
} else {
|
||||
if (_vm->_graphicsMan->_scrollStatus != 2) {
|
||||
if (getMouseX() > _vm->_graphicsMan->_scrollPosX + 620)
|
||||
_vm->_graphicsMan->_scrollPosX += _vm->_graphicsMan->_scrollSpeed;
|
||||
if (getMouseX() < _vm->_graphicsMan->_scrollPosX + 10)
|
||||
_vm->_graphicsMan->_scrollPosX -= _vm->_graphicsMan->_scrollSpeed;
|
||||
}
|
||||
_vm->_graphicsMan->_scrollPosX = CLIP(_vm->_graphicsMan->_scrollPosX, 0, SCREEN_WIDTH);
|
||||
if (_vm->_graphicsMan->_oldScrollPosX == _vm->_graphicsMan->_scrollPosX) {
|
||||
_vm->_graphicsMan->displayDirtyRects();
|
||||
} else {
|
||||
_vm->_fontMan->hideText(9);
|
||||
_vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_frontBuffer, _vm->_graphicsMan->_scrollPosX, 20, SCREEN_WIDTH, 440, 0, 20);
|
||||
_vm->_graphicsMan->resetRefreshRects();
|
||||
_vm->_graphicsMan->addRefreshRect(0, 20, SCREEN_WIDTH, SCREEN_HEIGHT - 20);
|
||||
|
||||
_vm->_graphicsMan->resetDirtyRects();
|
||||
|
||||
_startPos.x = _vm->_graphicsMan->_scrollPosX;
|
||||
_vm->_graphicsMan->_scrollOffset = _vm->_graphicsMan->_scrollPosX;
|
||||
}
|
||||
_vm->_graphicsMan->_oldScrollPosX = _vm->_graphicsMan->_scrollPosX;
|
||||
_startPos.x = _vm->_graphicsMan->_scrollPosX;
|
||||
_vm->_graphicsMan->_scrollOffset = _vm->_graphicsMan->_scrollPosX;
|
||||
}
|
||||
_curMouseButton = _mouseButton;
|
||||
_mouseButton = 0;
|
||||
_vm->_soundMan->checkSoundEnd();
|
||||
refreshEvents();
|
||||
}
|
||||
|
||||
void EventsManager::updateCursor() {
|
||||
// Backup the current sprite clipping bounds and reset them
|
||||
Common::Rect clipBounds(_vm->_graphicsMan->_minX, _vm->_graphicsMan->_minY,
|
||||
_vm->_graphicsMan->_maxX, _vm->_graphicsMan->_maxY);
|
||||
_vm->_graphicsMan->_minX = _vm->_graphicsMan->_minY = 0;
|
||||
_vm->_graphicsMan->_maxX = _vm->_objectsMan->getObjectWidth();
|
||||
_vm->_graphicsMan->_maxY = _vm->_objectsMan->getObjectHeight();
|
||||
int pitch = _vm->_graphicsMan->_lineNbr2;
|
||||
_vm->_graphicsMan->_lineNbr2 = _vm->_objectsMan->getObjectWidth();
|
||||
|
||||
// Create the temporary cursor surface
|
||||
byte *cursorSurface = new byte[_vm->_objectsMan->getObjectHeight() * _vm->_objectsMan->getObjectWidth()];
|
||||
Common::fill(cursorSurface, cursorSurface + _vm->_objectsMan->getObjectHeight() * _vm->_objectsMan->getObjectWidth(), 0);
|
||||
|
||||
if (_mouseCursorId != 23) {
|
||||
// Draw standard cursor
|
||||
_vm->_graphicsMan->drawVesaSprite(cursorSurface, _mouseCursor, 300, 300, _mouseSpriteId);
|
||||
} else {
|
||||
// Draw the active inventory object
|
||||
_vm->_graphicsMan->drawCompressedSprite(cursorSurface, _objectBuf, 300, 300, 0, 0, 0, false);
|
||||
}
|
||||
|
||||
// Reset the clipping bounds
|
||||
_vm->_graphicsMan->_minX = clipBounds.left;
|
||||
_vm->_graphicsMan->_minY = clipBounds.top;
|
||||
_vm->_graphicsMan->_maxX = clipBounds.right;
|
||||
_vm->_graphicsMan->_maxY = clipBounds.bottom;
|
||||
_vm->_graphicsMan->_lineNbr2 = pitch;
|
||||
|
||||
// Create a cursor palette
|
||||
Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
|
||||
|
||||
byte *cursorPalette = new byte[3 * PALETTE_SIZE];
|
||||
uint16 *paletteColors = (uint16 *)_vm->_graphicsMan->_palettePixels;
|
||||
|
||||
for (int i = 0; i < PALETTE_SIZE; i++) {
|
||||
uint8 r, g, b;
|
||||
pixelFormat.colorToRGB(READ_LE_UINT16(&paletteColors[i]), r, g, b);
|
||||
cursorPalette[3 * i] = r;
|
||||
cursorPalette[3 * i + 1] = g;
|
||||
cursorPalette[3 * i + 2] = b;
|
||||
}
|
||||
|
||||
// Calculate the X offset within the pointer image to the actual cursor data
|
||||
int xOffset = !_mouseLinuxFl ? 10 : 20;
|
||||
|
||||
// Set the ScummVM cursor from the surface
|
||||
CursorMan.replaceCursorPalette(cursorPalette, 0, PALETTE_SIZE - 1);
|
||||
CursorMan.replaceCursor(cursorSurface, _vm->_objectsMan->getObjectWidth(), _vm->_objectsMan->getObjectHeight(),
|
||||
xOffset, 0, 0, false);
|
||||
|
||||
// Delete the cursor surface and palette
|
||||
delete[] cursorPalette;
|
||||
delete[] cursorSurface;
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
93
engines/hopkins/events.h
Normal file
93
engines/hopkins/events.h
Normal 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 HOPKINS_EVENTS_H
|
||||
#define HOPKINS_EVENTS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/events.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
#define GAME_FRAME_RATE 50
|
||||
#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
enum DIALOG_KEY { KEY_NONE = 0, KEY_INVENTORY = 1, KEY_OPTIONS = 2, KEY_SAVE = 3, KEY_LOAD = 4 };
|
||||
|
||||
class EventsManager {
|
||||
private:
|
||||
int _oldIconId;
|
||||
uint32 _priorCounterTime;
|
||||
uint32 _priorFrameTime;
|
||||
bool _keyState[256];
|
||||
bool _mouseLinuxFl;
|
||||
int _mouseSizeX, _mouseSizeY;
|
||||
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
void pollEvents();
|
||||
void handleKey(const Common::Event &event);
|
||||
void checkForNextFrameCounter();
|
||||
void updateCursor();
|
||||
|
||||
public:
|
||||
DIALOG_KEY _gameKey;
|
||||
uint32 _rateCounter;
|
||||
uint32 _gameCounter;
|
||||
bool _escKeyFl;
|
||||
bool _mouseFl;
|
||||
bool _breakoutFl;
|
||||
Common::Point _startPos;
|
||||
Common::Point _mousePos;
|
||||
Common::Point _mouseOffset;
|
||||
int _mouseSpriteId;
|
||||
int _curMouseButton;
|
||||
int _mouseButton;
|
||||
int _mouseCursorId;
|
||||
byte *_objectBuf;
|
||||
byte *_mouseCursor;
|
||||
|
||||
EventsManager(HopkinsEngine *vm);
|
||||
~EventsManager();
|
||||
void clearAll();
|
||||
void initMouseData();
|
||||
|
||||
void delay(int totalMilli);
|
||||
void changeMouseCursor(int id);
|
||||
void refreshEvents();
|
||||
int waitKeyPress();
|
||||
int getMouseX();
|
||||
int getMouseY();
|
||||
int getMouseButton();
|
||||
void setMouseXY(Common::Point pos);
|
||||
void setMouseXY(int xp, int yp);
|
||||
void mouseOn();
|
||||
void mouseOff();
|
||||
void setMouseOn();
|
||||
void refreshScreenAndEvents();
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_EVENTS_H */
|
||||
265
engines/hopkins/files.cpp
Normal file
265
engines/hopkins/files.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/* 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 "hopkins/files.h"
|
||||
|
||||
#include "hopkins/hopkins.h"
|
||||
#include "hopkins/globals.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/system.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/str.h"
|
||||
#include "common/savefile.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
FileManager::FileManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
_catalogPos = 0;
|
||||
_catalogSize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a file
|
||||
*/
|
||||
byte *FileManager::loadFile(const Common::Path &file) {
|
||||
Common::File f;
|
||||
if (!f.open(file))
|
||||
error("Error opening %s", file.toString().c_str());
|
||||
|
||||
// Allocate space for the file contents
|
||||
size_t filesize = f.size();
|
||||
byte *data = _vm->_globals->allocMemory(filesize+1);
|
||||
if (!data)
|
||||
error("Error allocating space for file being loaded - %s", file.toString().c_str());
|
||||
|
||||
readStream(f, data, filesize);
|
||||
f.close();
|
||||
data[filesize] = '\0';
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a given number of bytes from a Stream into a pre-allocated buffer
|
||||
*/
|
||||
int FileManager::readStream(Common::ReadStream &stream, void *buf, size_t nbytes) {
|
||||
return stream.read(buf, nbytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* The original censorship was based on blood.dat file.
|
||||
* It's now using the config manager and a per-engine GUI option.
|
||||
*/
|
||||
void FileManager::initCensorship() {
|
||||
_vm->_globals->_censorshipFl = !ConfMan.getBool("enable_gore");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file is present
|
||||
*/
|
||||
bool FileManager::fileExists(const Common::Path &file) {
|
||||
Common::File f;
|
||||
|
||||
return f.exists(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search file in Cat file
|
||||
*/
|
||||
byte *FileManager::searchCat(const Common::Path &file, CatMode mode, bool &fileFoundFl) {
|
||||
byte *ptr = nullptr;
|
||||
fileFoundFl = true;
|
||||
Common::File f;
|
||||
|
||||
Common::String filename = file.toString('/');
|
||||
Common::Path secondaryFilename;
|
||||
filename.toUppercase();
|
||||
|
||||
switch (mode) {
|
||||
case RES_INI:
|
||||
if (!f.exists("RES_INI.CAT")) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile("RES_INI.CAT");
|
||||
secondaryFilename = "RES_INI.RES";
|
||||
break;
|
||||
|
||||
case RES_REP:
|
||||
if (!f.exists("RES_REP.CAT")) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile("RES_REP.CAT");
|
||||
secondaryFilename = "RES_REP.RES";
|
||||
break;
|
||||
|
||||
case RES_LIN:
|
||||
if (!f.exists("RES_LIN.CAT")) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile("RES_LIN.CAT");
|
||||
secondaryFilename = "RES_LIN.RES";
|
||||
break;
|
||||
|
||||
case RES_PER:
|
||||
if (!f.exists("RES_PER.CAT")) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile("RES_PER.CAT");
|
||||
secondaryFilename = "RES_PER.RES";
|
||||
break;
|
||||
|
||||
case RES_PIC:
|
||||
if (!f.exists("PIC.CAT")) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile("PIC.CAT");
|
||||
break;
|
||||
|
||||
case RES_SAN:
|
||||
if (!f.exists("RES_SAN.CAT")) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile("RES_SAN.CAT");
|
||||
break;
|
||||
|
||||
case RES_SLI:
|
||||
if (!f.exists("RES_SLI.CAT")) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile("RES_SLI.CAT");
|
||||
break;
|
||||
|
||||
case RES_VOI: {
|
||||
Common::Path tmpFilename;
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
|
||||
tmpFilename = "ENG_VOI.CAT";
|
||||
// Win95 and Linux versions uses another set of names
|
||||
else {
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_EN:
|
||||
tmpFilename = "RES_VAN.CAT";
|
||||
break;
|
||||
case LANG_FR:
|
||||
tmpFilename = "RES_VFR.CAT";
|
||||
break;
|
||||
case LANG_SP:
|
||||
tmpFilename = "RES_VES.CAT";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f.exists(tmpFilename)) {
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ptr = loadFile(tmpFilename);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Scan for an entry in the catalogue
|
||||
byte *result;
|
||||
bool matchFlag = false;
|
||||
int offsetVal = 0;
|
||||
|
||||
while (!matchFlag) {
|
||||
Common::String name = (const char *)ptr + offsetVal;
|
||||
|
||||
if (name == filename) {
|
||||
// Found entry for file, so get it's details from the catalogue entry
|
||||
const byte *pData = ptr + offsetVal;
|
||||
_catalogPos = READ_LE_UINT32(pData + 15);
|
||||
_catalogSize = READ_LE_UINT32(pData + 19);
|
||||
matchFlag = true;
|
||||
}
|
||||
|
||||
if (name == "FINIS") {
|
||||
_vm->_globals->freeMemory(ptr);
|
||||
fileFoundFl = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
offsetVal += 23;
|
||||
}
|
||||
|
||||
_vm->_globals->freeMemory(ptr);
|
||||
|
||||
if (!secondaryFilename.empty()) {
|
||||
if (!f.open(secondaryFilename))
|
||||
error("CHARGE_FICHIER");
|
||||
|
||||
f.seek(_catalogPos);
|
||||
|
||||
byte *catData = _vm->_globals->allocMemory(_catalogSize);
|
||||
if (catData == nullptr)
|
||||
error("CHARGE_FICHIER");
|
||||
|
||||
readStream(f, catData, _catalogSize);
|
||||
f.close();
|
||||
result = catData;
|
||||
} else {
|
||||
result = nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of a file. Throws an error if the file can't be found
|
||||
*/
|
||||
uint32 FileManager::fileSize(const Common::Path &filename) {
|
||||
Common::File f;
|
||||
uint32 size;
|
||||
|
||||
if (!f.open(filename))
|
||||
error("Could not find file %s", filename.toString().c_str());
|
||||
|
||||
size = f.size();
|
||||
f.close();
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
59
engines/hopkins/files.h
Normal file
59
engines/hopkins/files.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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 HOPKINS_FILES_H
|
||||
#define HOPKINS_FILES_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Common {
|
||||
class ReadStream;
|
||||
class Path;
|
||||
}
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
// RES_ANI = 4 has been removed because it's not used
|
||||
enum CatMode { RES_INI = 1, RES_REP = 2, RES_LIN = 3, RES_PER = 5,
|
||||
RES_PIC = 6, RES_SAN = 7, RES_SLI = 8, RES_VOI = 9 };
|
||||
|
||||
class FileManager {
|
||||
public:
|
||||
uint32 _catalogPos;
|
||||
uint32 _catalogSize;
|
||||
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
FileManager(HopkinsEngine *vm);
|
||||
|
||||
bool fileExists(const Common::Path &file);
|
||||
byte *loadFile(const Common::Path &file);
|
||||
int readStream(Common::ReadStream &stream, void *buf, size_t nbytes);
|
||||
void initCensorship();
|
||||
byte *searchCat(const Common::Path &file, CatMode mode, bool &fileFoundFl);
|
||||
uint32 fileSize(const Common::Path &filename);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_GLOBALS_H */
|
||||
498
engines/hopkins/font.cpp
Normal file
498
engines/hopkins/font.cpp
Normal file
@@ -0,0 +1,498 @@
|
||||
/* 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 "hopkins/font.h"
|
||||
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/graphics.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
#include "hopkins/objects.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/file.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
FontManager::FontManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
clearAll();
|
||||
}
|
||||
|
||||
FontManager::~FontManager() {
|
||||
_vm->_globals->freeMemory(_font);
|
||||
_vm->_globals->freeMemory(_zoneText);
|
||||
}
|
||||
|
||||
void FontManager::loadZoneText() {
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_EN:
|
||||
_zoneText = _vm->_fileIO->loadFile("ZONEAN.TXT");
|
||||
break;
|
||||
case LANG_FR:
|
||||
_zoneText = _vm->_fileIO->loadFile("ZONE01.TXT");
|
||||
break;
|
||||
case LANG_SP:
|
||||
_zoneText = _vm->_fileIO->loadFile("ZONEES.TXT");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FontManager::clearAll() {
|
||||
_font = nullptr;
|
||||
_fontFixedHeight = 0;
|
||||
_fontFixedWidth = 0;
|
||||
|
||||
for (int idx = 0; idx < 12; ++idx) {
|
||||
Common::fill((byte *)&_text[idx], (byte *)&_text[idx] + sizeof(TxtItem), 0);
|
||||
|
||||
_textList[idx]._enabledFl = false;
|
||||
_textList[idx]._height = 0;
|
||||
_textList[idx]._width = 0;
|
||||
_textList[idx]._pos.x = 0;
|
||||
_textList[idx]._pos.y = 0;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < 21; idx++)
|
||||
_textSortArray[idx] = 0;
|
||||
|
||||
_oldName = Common::String("");
|
||||
_indexName = Common::String("");
|
||||
|
||||
for (int idx = 0; idx < 4048; idx++)
|
||||
_index[idx] = 0;
|
||||
|
||||
_tempText = nullptr;
|
||||
_zoneText = nullptr;
|
||||
|
||||
_boxWidth = 240;
|
||||
}
|
||||
|
||||
void FontManager::initData() {
|
||||
_font = _vm->_fileIO->loadFile("FONTE3.SPR");
|
||||
_fontFixedWidth = 12;
|
||||
_fontFixedHeight = 21;
|
||||
loadZoneText();
|
||||
}
|
||||
/**
|
||||
* Display Text
|
||||
*/
|
||||
void FontManager::showText(int idx) {
|
||||
if ((idx - 5) > MAX_TEXT)
|
||||
error("Attempted to display text > MAX_TEXT.");
|
||||
|
||||
TxtItem &txt = _text[idx - 5];
|
||||
txt._textOnFl = true;
|
||||
txt._textLoadedFl = false;
|
||||
|
||||
txt._textBlock = _vm->_globals->freeMemory(txt._textBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide text
|
||||
*/
|
||||
void FontManager::hideText(int idx) {
|
||||
if ((idx - 5) > MAX_TEXT)
|
||||
error("Attempted to display text > MAX_TEXT.");
|
||||
|
||||
TxtItem &txt = _text[idx - 5];
|
||||
txt._textOnFl = false;
|
||||
txt._textLoadedFl = false;
|
||||
txt._textBlock = _vm->_globals->freeMemory(txt._textBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Text Color
|
||||
*/
|
||||
void FontManager::setTextColor(int idx, byte colByte) {
|
||||
_text[idx - 5]._color = colByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Text Optimal Color
|
||||
*/
|
||||
void FontManager::setOptimalColor(int idx1, int idx2, int idx3, int idx4) {
|
||||
setTextColor(idx1, 255);
|
||||
setTextColor(idx2, 255);
|
||||
setTextColor(idx3, 255);
|
||||
setTextColor(idx4, 253);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init text structure
|
||||
*/
|
||||
void FontManager::initTextBuffers(int idx, int messageId, const Common::Path &filename, int xp, int yp, int textType, int length, int color) {
|
||||
assert(idx - 5 >= 0 && (idx - 5) <= MAX_TEXT);
|
||||
|
||||
TxtItem &txt = _text[idx - 5];
|
||||
txt._textOnFl = false;
|
||||
txt._filename = filename;
|
||||
txt._pos.x = xp;
|
||||
txt._pos.y = yp;
|
||||
txt._messageId = messageId;
|
||||
txt._textType = textType;
|
||||
txt._length = length;
|
||||
txt._color = color;
|
||||
}
|
||||
|
||||
// Box
|
||||
void FontManager::box(int idx, int messageId, const Common::Path &filename, int xp, int yp) {
|
||||
int textPosX = xp;
|
||||
if (idx < 0)
|
||||
error("Bad number for text");
|
||||
_fontFixedWidth = 11;
|
||||
|
||||
_boxWidth = 11 * _text[idx]._length;
|
||||
if (_text[idx]._textLoadedFl) {
|
||||
int textType = _text[idx]._textType;
|
||||
if (textType != 6 && textType != 1 && textType != 3 && textType != 5) {
|
||||
int yCurrent = yp + 5;
|
||||
for (int lineNum = 0; lineNum < _text[idx]._lineCount; ++lineNum) {
|
||||
displayText(xp + 5, yCurrent, _text[idx]._lines[lineNum], _text[idx]._color);
|
||||
yCurrent += _fontFixedHeight + 1;
|
||||
}
|
||||
} else {
|
||||
int height = _text[idx]._height;
|
||||
int width = _text[idx]._width;
|
||||
_vm->_graphicsMan->restoreSurfaceRect(
|
||||
_vm->_graphicsMan->_frontBuffer,
|
||||
_text[idx]._textBlock,
|
||||
xp,
|
||||
yp,
|
||||
_text[idx]._width,
|
||||
_text[idx]._height);
|
||||
_vm->_graphicsMan->addDirtyRect(xp, yp, xp + width, yp + height);
|
||||
}
|
||||
} else {
|
||||
int lineCount = 0;
|
||||
for (int i = 0; i <= 19; i++)
|
||||
_textSortArray[i] = 0;
|
||||
|
||||
_text[idx]._textLoadedFl = true;
|
||||
Common::String basename(filename.baseName());
|
||||
if (filename != _oldName) {
|
||||
// Starting to access a new file, so read in the index file for the file
|
||||
_oldName = filename;
|
||||
_indexName = filename.getParent();
|
||||
_indexName.joinInPlace(Common::String(basename.c_str(), basename.size() - 3));
|
||||
_indexName.appendInPlace("IND");
|
||||
|
||||
Common::File f;
|
||||
if (!f.open(_indexName))
|
||||
error("Error opening file - %s", _indexName.toString().c_str());
|
||||
int filesize = f.size();
|
||||
for (int i = 0; i < (filesize / 4); ++i)
|
||||
_index[i] = f.readUint32LE();
|
||||
f.close();
|
||||
}
|
||||
int bufSize;
|
||||
if (basename[0] != 'Z' || basename[1] != 'O') {
|
||||
Common::File f;
|
||||
if (!f.open(filename))
|
||||
error("Error opening file - %s", _indexName.toString().c_str());
|
||||
|
||||
bufSize = 2048;
|
||||
f.seek(_index[messageId]);
|
||||
|
||||
_tempText = _vm->_globals->allocMemory(2058);
|
||||
if (_tempText == nullptr)
|
||||
error("Error allocating text");
|
||||
|
||||
Common::fill(&_tempText[0], &_tempText[2058], 0);
|
||||
f.read(_tempText, 2048);
|
||||
f.close();
|
||||
} else {
|
||||
bufSize = 100;
|
||||
_tempText = _vm->_globals->allocMemory(110);
|
||||
Common::fill(&_tempText[0], &_tempText[110], 0);
|
||||
memcpy(_tempText, _zoneText + _index[messageId], 96);
|
||||
WRITE_LE_UINT16((uint16 *)_tempText + 48, READ_LE_INT16(_zoneText + _index[messageId] + 96));
|
||||
}
|
||||
byte *curTempTextPtr = _tempText;
|
||||
for (int i = 0; i < bufSize; i++) {
|
||||
byte curChar = *curTempTextPtr;
|
||||
if ((byte)(*curTempTextPtr + 46) > 27) {
|
||||
if ((byte)(curChar + 80) > 27) {
|
||||
if ((byte)(curChar - 65) <= 25 || (byte)(curChar - 97) <= 25)
|
||||
curChar = 32;
|
||||
} else {
|
||||
curChar -= 79;
|
||||
}
|
||||
} else {
|
||||
curChar += 111;
|
||||
}
|
||||
*curTempTextPtr = curChar;
|
||||
curTempTextPtr++;
|
||||
};
|
||||
|
||||
int textLength;
|
||||
for (textLength = 0; textLength < bufSize; textLength++) {
|
||||
byte curChar = _tempText[textLength];
|
||||
if (curChar == '\r' || curChar == '\n') {
|
||||
_tempText[textLength] = 0;
|
||||
if (!_text[idx]._length)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufSize && bufSize > textLength) {
|
||||
_text[idx]._length = textLength;
|
||||
_boxWidth = 0;
|
||||
|
||||
for (int curStrIdx = 0; curStrIdx < textLength + 1; curStrIdx++) {
|
||||
byte curChar = _tempText[curStrIdx];
|
||||
if (curChar <= 31)
|
||||
curChar = ' ';
|
||||
_boxWidth += _vm->_objectsMan->getWidth(_font, curChar - 32);
|
||||
}
|
||||
|
||||
_boxWidth += 2;
|
||||
_text[idx]._pos.x = 320 - abs(_boxWidth / 2);
|
||||
textPosX = _vm->_events->_startPos.x + _text[idx]._pos.x;
|
||||
lineCount = 1;
|
||||
_text[idx]._lines[0] = Common::String((const char *)_tempText, textLength);
|
||||
} else {
|
||||
if (!_boxWidth)
|
||||
_boxWidth = 240;
|
||||
int tempTextIdx = 0;
|
||||
int lineSize;
|
||||
byte curChar;
|
||||
do {
|
||||
int curLineSize = 0;
|
||||
int ptrb = _boxWidth - 4;
|
||||
for (;;) {
|
||||
lineSize = curLineSize;
|
||||
do {
|
||||
curChar = _tempText[tempTextIdx + curLineSize++];
|
||||
} while (curChar != ' ' && curChar != '%');
|
||||
if (curLineSize >= ptrb / _fontFixedWidth) {
|
||||
if (curChar == '%')
|
||||
curChar = ' ';
|
||||
break;
|
||||
}
|
||||
if (curChar == '%') {
|
||||
lineSize = curLineSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// WORKAROUND: Perhaps due to the usage of ScummVM strings here, recalculate what the
|
||||
// actual length of the line to be copied will be. Otherwise, you can see artifacts,
|
||||
// such as a single character beyond the end of string NULL.
|
||||
int actualSize = 0;
|
||||
while (actualSize < lineSize && _tempText[tempTextIdx + actualSize])
|
||||
++actualSize;
|
||||
|
||||
_text[idx]._lines[lineCount] = Common::String((const char *)_tempText + tempTextIdx, actualSize);
|
||||
_textSortArray[lineCount++] = lineSize;
|
||||
|
||||
tempTextIdx += lineSize;
|
||||
} while (curChar != '%');
|
||||
|
||||
for (int i = 0; i <= 19; i++) {
|
||||
if (_textSortArray[i] <= 0) {
|
||||
_textSortArray[i] = 0;
|
||||
} else {
|
||||
int ptrc = 0;
|
||||
for (int curIdx = 0; curIdx < _textSortArray[i] - 1; curIdx++) {
|
||||
Common::String &line = _text[idx]._lines[i];
|
||||
byte curChar2 = (curIdx >= (int)line.size()) ? '\0' : line.c_str()[curIdx];
|
||||
if (curChar2 <= 31)
|
||||
curChar2 = ' ';
|
||||
ptrc += _vm->_objectsMan->getWidth(_font, (byte)curChar2 - 32);
|
||||
}
|
||||
_textSortArray[i] = ptrc;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i <= 19; i++) {
|
||||
for (int j = i + 1; j != i; j = (j + 1) % 20) {
|
||||
if (_textSortArray[i] < _textSortArray[j])
|
||||
_textSortArray[i] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i <= 19; i++) {
|
||||
if (_textSortArray[i])
|
||||
_boxWidth = _textSortArray[i];
|
||||
}
|
||||
|
||||
if ((_text[idx]._textType < 2) || (_text[idx]._textType > 3)) {
|
||||
int i;
|
||||
for (i = xp - _vm->_events->_startPos.x; _boxWidth + i > 638 && i > -2 && _text[idx]._textType; i -= 2)
|
||||
;
|
||||
_text[idx]._pos.x = i;
|
||||
textPosX = _vm->_events->_startPos.x + i;
|
||||
} else {
|
||||
_text[idx]._pos.x = textPosX;
|
||||
}
|
||||
}
|
||||
int posX = textPosX;
|
||||
int posY = yp;
|
||||
int saveWidth = _boxWidth + 10;
|
||||
int saveHeight = (_fontFixedHeight + 1) * lineCount + 12;
|
||||
if (_text[idx]._textType == 6) {
|
||||
_text[idx]._pos.x = 315 - abs(saveWidth / 2);
|
||||
textPosX = posX = _vm->_events->_startPos.x + _text[idx]._pos.x;
|
||||
_text[idx]._pos.y = posY = 50;
|
||||
}
|
||||
int textType = _text[idx]._textType;
|
||||
if (textType == 1 || textType == 3 || textType == 5 || textType == 6) {
|
||||
int size = saveHeight * saveWidth;
|
||||
byte *ptrd = _vm->_globals->allocMemory(size);
|
||||
if (ptrd == nullptr)
|
||||
error("Cutting a block for text box (%d)", size);
|
||||
|
||||
_vm->_graphicsMan->copySurfaceRect(_vm->_graphicsMan->_frontBuffer, ptrd, posX, posY, saveWidth, saveHeight);
|
||||
_vm->_graphicsMan->fillSurface(ptrd, _vm->_graphicsMan->_colorTable, size);
|
||||
_vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, ptrd, posX, posY, saveWidth, saveHeight);
|
||||
_vm->_globals->freeMemory(ptrd);
|
||||
|
||||
_vm->_graphicsMan->drawHorizontalLine(_vm->_graphicsMan->_frontBuffer, posX, posY, saveWidth, (byte)-2);
|
||||
_vm->_graphicsMan->drawHorizontalLine(_vm->_graphicsMan->_frontBuffer, posX, saveHeight + posY, saveWidth, (byte)-2);
|
||||
_vm->_graphicsMan->drawVerticalLine(_vm->_graphicsMan->_frontBuffer, posX, posY, saveHeight, (byte)-2);
|
||||
_vm->_graphicsMan->drawVerticalLine(_vm->_graphicsMan->_frontBuffer, saveWidth + posX, posY, saveHeight, (byte)-2);
|
||||
}
|
||||
_text[idx]._lineCount = lineCount;
|
||||
int textPosY = posY + 5;
|
||||
|
||||
for (int lineNum = 0; lineNum < lineCount; ++lineNum) {
|
||||
displayText(textPosX + 5, textPosY, _text[idx]._lines[lineNum], _text[idx]._color);
|
||||
textPosY += _fontFixedHeight + 1;
|
||||
}
|
||||
|
||||
int blockWidth = saveWidth + 1;
|
||||
int blockHeight = saveHeight + 1;
|
||||
|
||||
_text[idx]._width = blockWidth;
|
||||
_text[idx]._height = blockHeight;
|
||||
textType = _text[idx]._textType;
|
||||
if (textType == 6 || textType == 1 || textType == 3 || textType == 5) {
|
||||
_text[idx]._textBlock = _vm->_globals->freeMemory(_text[idx]._textBlock);
|
||||
int blockSize = blockHeight * blockWidth;
|
||||
byte *ptre = _vm->_globals->allocMemory(blockSize + 20);
|
||||
if (ptre == nullptr)
|
||||
error("Cutting a block for text box (%d)", blockSize);
|
||||
|
||||
_text[idx]._textBlock = ptre;
|
||||
_text[idx]._width = blockWidth;
|
||||
_text[idx]._height = blockHeight;
|
||||
_vm->_graphicsMan->copySurfaceRect(_vm->_graphicsMan->_frontBuffer, _text[idx]._textBlock, posX, posY, _text[idx]._width, blockHeight);
|
||||
}
|
||||
_tempText = _vm->_globals->freeMemory(_tempText);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly display text (using a VESA segment)
|
||||
*/
|
||||
void FontManager::displayTextVesa(int xp, int yp, const Common::String &message, int col) {
|
||||
int charIndex;
|
||||
int currentX = xp;
|
||||
|
||||
const char *srcP = message.c_str();
|
||||
for (;;) {
|
||||
byte currChar = *srcP++;
|
||||
if (!currChar)
|
||||
break;
|
||||
if (currChar >= 32) {
|
||||
charIndex = currChar - 32;
|
||||
_vm->_graphicsMan->displayFont(_vm->_graphicsMan->_frontBuffer, _font, currentX, yp, currChar - 32, col);
|
||||
currentX += _vm->_objectsMan->getWidth(_font, charIndex);
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphicsMan->addDirtyRect(xp, yp, currentX, yp + 12);
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly display text
|
||||
*/
|
||||
void FontManager::displayText(int xp, int yp, const Common::String &message, int col) {
|
||||
for (uint idx = 0; idx < message.size(); ++idx) {
|
||||
byte currentChar = (byte)message[idx];
|
||||
|
||||
if (currentChar > 31) {
|
||||
int characterIndex = currentChar - 32;
|
||||
_vm->_graphicsMan->displayFont(_vm->_graphicsMan->_frontBuffer, _font, xp, yp, characterIndex, col);
|
||||
_vm->_graphicsMan->addDirtyRect(xp, yp, xp + _vm->_objectsMan->getWidth(_font, characterIndex) + 1, yp + _vm->_objectsMan->getHeight(_font, characterIndex) + 1);
|
||||
xp += _vm->_objectsMan->getWidth(_font, characterIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute character width and render text using variable width fonts
|
||||
*/
|
||||
void FontManager::renderTextDisplay(int xp, int yp, const Common::String &msg, int col) {
|
||||
const char *srcP = msg.c_str();
|
||||
int charEndPosX = xp;
|
||||
int fontCol = col;
|
||||
byte curChar = *srcP++;
|
||||
while (curChar) {
|
||||
if (curChar == '&') {
|
||||
fontCol = 2;
|
||||
curChar = *srcP++;
|
||||
}
|
||||
if (curChar == '$') {
|
||||
fontCol = 4;
|
||||
curChar = *srcP++;
|
||||
}
|
||||
if (!curChar)
|
||||
break;
|
||||
if (curChar >= 32) {
|
||||
byte printChar = curChar - 32;
|
||||
_vm->_graphicsMan->displayFont(_vm->_graphicsMan->_frontBuffer, _font, charEndPosX, yp, printChar, fontCol);
|
||||
|
||||
// UGLY HACK: For some obscure reason, the BeOS and OS/2 versions use another font file, which doesn't have variable width.
|
||||
// All the fonts have a length of 9, which results in completely broken text in the computer.
|
||||
// This horrible workaround fixes the English versions of the game. So far, no other languages are known for those platforms.
|
||||
// Just in case, all the accentuated characters are handled properly, which *should* be OK for the other languages too.
|
||||
int charWidth;
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
|
||||
if ((curChar >= 'A' && curChar <= 'Z') || (curChar >= 'a' && curChar <= 'z' && curChar != 'm' && curChar != 'w') || (curChar >= '0' && curChar <= '9') || curChar == '*' || (curChar >= 128 && curChar <= 168))
|
||||
charWidth = _vm->_objectsMan->getWidth(_font, printChar) - 1;
|
||||
else if (curChar == 'm' || curChar == 'w')
|
||||
charWidth = _vm->_objectsMan->getWidth(_font, printChar);
|
||||
else
|
||||
charWidth = 6;
|
||||
} else
|
||||
charWidth = _vm->_objectsMan->getWidth(_font, printChar);
|
||||
|
||||
int charStartPosX = charEndPosX;
|
||||
charEndPosX += charWidth;
|
||||
_vm->_graphicsMan->addDirtyRect(charStartPosX, yp, charEndPosX, yp + 12);
|
||||
if (_vm->_events->_escKeyFl) {
|
||||
_vm->_globals->_eventMode = EVENTMODE_IGNORE;
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
} else {
|
||||
_vm->_globals->_eventMode = EVENTMODE_ALT;
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
_vm->_globals->_eventMode = EVENTMODE_IGNORE;
|
||||
}
|
||||
}
|
||||
curChar = *srcP++;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
97
engines/hopkins/font.h
Normal file
97
engines/hopkins/font.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HOPKINS_FONT_H
|
||||
#define HOPKINS_FONT_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/events.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
#define MAX_TEXT 11
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
struct TxtItem {
|
||||
bool _textOnFl;
|
||||
Common::Path _filename;
|
||||
Common::Point _pos;
|
||||
int _messageId;
|
||||
int _lineCount;
|
||||
Common::String _lines[10];
|
||||
int _textType;
|
||||
int _length;
|
||||
byte *_textBlock;
|
||||
int16 _width;
|
||||
int16 _height;
|
||||
bool _textLoadedFl;
|
||||
int _color;
|
||||
};
|
||||
|
||||
struct TxtItemList {
|
||||
bool _enabledFl;
|
||||
Common::Point _pos;
|
||||
int16 _width;
|
||||
int16 _height;
|
||||
};
|
||||
|
||||
class FontManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
void setTextColor(int idx, byte colByte);
|
||||
|
||||
int _textSortArray[21];
|
||||
Common::Path _oldName;
|
||||
Common::Path _indexName;
|
||||
int _index[4048];
|
||||
byte *_tempText;
|
||||
byte *_zoneText;
|
||||
int _boxWidth;
|
||||
|
||||
void loadZoneText();
|
||||
public:
|
||||
byte *_font;
|
||||
int _fontFixedWidth;
|
||||
int _fontFixedHeight;
|
||||
TxtItem _text[12];
|
||||
TxtItemList _textList[12];
|
||||
|
||||
FontManager(HopkinsEngine *vm);
|
||||
~FontManager();
|
||||
void clearAll();
|
||||
void initData();
|
||||
|
||||
void showText(int idx);
|
||||
void hideText(int idx);
|
||||
void initTextBuffers(int idx, int messageId, const Common::Path &filename, int xp, int yp, int textType, int length, int color);
|
||||
void displayText(int xp, int yp, const Common::String &message, int col);
|
||||
void displayTextVesa(int xp, int yp, const Common::String &message, int col);
|
||||
void renderTextDisplay(int xp, int yp, const Common::String &msg, int col);
|
||||
void setOptimalColor(int idx1, int idx2, int idx3, int idx4);
|
||||
void box(int idx, int messageId, const Common::Path &filename, int xp, int yp);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_FONT_H */
|
||||
215
engines/hopkins/globals.cpp
Normal file
215
engines/hopkins/globals.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
/* 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 "hopkins/globals.h"
|
||||
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/font.h"
|
||||
#include "hopkins/graphics.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
|
||||
#include "common/textconsole.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
// Default data for the Hopkins array
|
||||
|
||||
const int HOPKINS_PERSO_0[] = {
|
||||
0, -2, 0, -3, 0, -6, 0, -1, 0, -3, 0, -3, 0, -5, 0, -3, 0, -6, 0, -3, 0, -3, 0, -3,
|
||||
9, -4, 8, -4, 6, -2, 9, -2, 9, -3, 9, -3, 9, -4, 9, -2, 9, -2, 8, -2, 9, -3, 9, -2,
|
||||
13, 0, 13, 0, 13, 0, 13, 0, 14, 0, 13, 0, 13, 0, 12, 0, 12, 0, 14, 0, 13, 0, 14, 0,
|
||||
10, 3, 9, 3, 10, 4, 8, 2, 7, 1, 10, 2, 9, 2, 7, 4, 7, 3, 8, 0, 9, 1, 9, 1, 0, 4, 0,
|
||||
4, 0, 6, 0, 3, 0, 4, 0, 3, 0, 4, 0, 4, 0, 6, 0, 3, 0, 3, 0, 3
|
||||
};
|
||||
|
||||
const int HOPKINS_PERSO_1[] = {
|
||||
0, -2, 0, -2, 0, -5, 0, -1, 0, -2, 0, -2, 0, -4, 0, -2, 0, -5, 0, -2, 0, -2, 0, -2,
|
||||
11, 0, 10, 0, 11, 0, 11, 0, 11, 0, 11, 0, 12, 0, 11, 0, 9, 0, 10, 0, 11, 0, 11, 0,
|
||||
11, 0, 10, 0, 11, 0, 11, 0, 11, 0, 11, 0, 12, 0, 11, 0, 9, 0, 10, 0, 11, 0, 11, 0,
|
||||
11, 0, 10, 0, 11, 0, 11, 0, 11, 0, 11, 0, 12, 0, 11, 0, 9, 0, 10, 0, 11, 0, 11, 0,
|
||||
0, 3, 0, 3, 0, 5, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 5, 0, 3, 0, 3, 0, 3
|
||||
};
|
||||
|
||||
const int HOPKINS_PERSO_2[] = {
|
||||
0, -2, 0, 0, 0, -3, 0, -2, 0, -2, 0, -1, 0, -2, 0, -1, 0, -3, 0, -2, 0, -2, 0, -2,
|
||||
8, 0, 9, 0, 5, 0, 9, 0, 7, 0, 7, 0, 7, 0, 7, 0, 6, 0, 7, 0, 6, 0, 9, 0, 8, 0, 9, 0,
|
||||
5, 0, 9, 0, 7, 0, 7, 0, 7, 0, 7, 0, 6, 0, 7, 0, 6, 0, 9, 0, 8, 0, 9, 0, 5, 0, 9, 0,
|
||||
7, 0, 7, 0, 7, 0, 7, 0, 6, 0, 7, 0, 6, 0, 9, 0, 0, 2, 0, 0, 0, 2, 0, 1, 0, 2, 0, 2,
|
||||
0, 2, 0, 2, 0, 2, 0, 1, 0, 2, 0, 2
|
||||
};
|
||||
|
||||
Globals::Globals(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
// Initialize array properties
|
||||
for (int i = 0; i < 500; ++i)
|
||||
_spriteSize[i] = 0;
|
||||
for (int i = 0; i < 70; ++i)
|
||||
Common::fill((byte *)&_hopkinsItem[i], (byte *)&_hopkinsItem[i] + sizeof(HopkinsItem), 0);
|
||||
|
||||
for (int i = 0; i < 36; ++i)
|
||||
_inventory[i] = 0;
|
||||
|
||||
// Initialize fields
|
||||
_language = LANG_EN;
|
||||
|
||||
_linuxEndDemoFl = false;
|
||||
_speed = 1;
|
||||
_eventMode = EVENTMODE_DEFAULT;
|
||||
_exitId = 0;
|
||||
_characterSpriteBuf = nullptr;
|
||||
_screenId = 0;
|
||||
_prevScreenId = 0;
|
||||
_characterMaxPosY = 0;
|
||||
_menuScrollSpeed = 0;
|
||||
_menuSpeed = 0;
|
||||
_menuSoundOff = 0;
|
||||
_menuVoiceOff = 0;
|
||||
_menuMusicOff = 0;
|
||||
_menuTextOff = 0;
|
||||
_menuDisplayType = 0;
|
||||
_checkDistanceFl = false;
|
||||
_characterType = CHARACTER_HOPKINS;
|
||||
_actionMoveTo = false;
|
||||
_actionDirection = DIR_NONE;
|
||||
|
||||
_creditsStartX = -1;
|
||||
_creditsEndX = -1;
|
||||
_creditsStartY = -1;
|
||||
_creditsEndY = -1;
|
||||
_creditsPosY = 0;
|
||||
_creditsLineNumb = 0;
|
||||
memset(_creditsItem, 0, 12000);
|
||||
_creditsStep = 0;
|
||||
|
||||
_oceanDirection = DIR_NONE;
|
||||
|
||||
// Initialize pointers
|
||||
_levelSpriteBuf = nullptr;
|
||||
_saveData = nullptr;
|
||||
_answerBuffer = nullptr;
|
||||
_characterSpriteBuf = nullptr;
|
||||
_optionDialogSpr = nullptr;
|
||||
|
||||
// Reset flags
|
||||
_censorshipFl = false;
|
||||
_disableInventFl = false;
|
||||
_freezeCharacterFl = false;
|
||||
_optionDialogFl = false;
|
||||
_introSpeechOffFl = false;
|
||||
_cityMapEnabledFl = false;
|
||||
|
||||
_baseMapColor = 50;
|
||||
_curRoomNum = 0;
|
||||
}
|
||||
|
||||
Globals::~Globals() {
|
||||
freeMemory(_levelSpriteBuf);
|
||||
freeMemory((byte *)_saveData);
|
||||
freeMemory(_answerBuffer);
|
||||
freeMemory(_characterSpriteBuf);
|
||||
}
|
||||
|
||||
void Globals::setConfig() {
|
||||
// CHECKME: Should be in Globals() but it doesn't work
|
||||
// The Polish version is a translation of the English version. The filenames are the same.
|
||||
// The Russian version looks like a translation of the English version, based on the filenames.
|
||||
switch (_vm->getLanguage()) {
|
||||
case Common::EN_ANY:
|
||||
case Common::PL_POL:
|
||||
case Common::RU_RUS:
|
||||
_language = LANG_EN;
|
||||
break;
|
||||
case Common::FR_FRA:
|
||||
_language = LANG_FR;
|
||||
break;
|
||||
case Common::ES_ESP:
|
||||
_language = LANG_SP;
|
||||
break;
|
||||
default:
|
||||
error("Hopkins - SetConfig(): Unknown language in internal language mapping");
|
||||
break;
|
||||
}
|
||||
// End of CHECKME
|
||||
|
||||
switch (_language) {
|
||||
case LANG_EN:
|
||||
_zoneFilename = "ZONEAN.TXT";
|
||||
_textFilename = "TEXTEAN.TXT";
|
||||
break;
|
||||
case LANG_FR:
|
||||
_zoneFilename = "ZONE01.TXT";
|
||||
_textFilename = "TEXTE01.TXT";
|
||||
break;
|
||||
case LANG_SP:
|
||||
_zoneFilename = "ZONEES.TXT";
|
||||
_textFilename = "TEXTEES.TXT";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Globals::clearAll() {
|
||||
_vm->_fontMan->clearAll();
|
||||
_vm->_dialog->clearAll();
|
||||
_answerBuffer = nullptr;
|
||||
_levelSpriteBuf = nullptr;
|
||||
_saveData = nullptr;
|
||||
_vm->_objectsMan->_curObjectIndex = 0;
|
||||
|
||||
_vm->_linesMan->clearAll();
|
||||
_vm->_objectsMan->clearAll();
|
||||
|
||||
_saveData = (Savegame *)malloc(sizeof(Savegame));
|
||||
_saveData->reset();
|
||||
|
||||
_vm->_events->clearAll();
|
||||
}
|
||||
|
||||
void Globals::loadCharacterData() {
|
||||
const int *srcList[] = { HOPKINS_PERSO_0, HOPKINS_PERSO_1, HOPKINS_PERSO_2 };
|
||||
const int *srcP = srcList[_characterType];
|
||||
|
||||
for (int idx = 0; idx < 240 / 4; ++idx) {
|
||||
_hopkinsItem[idx]._speedX = *srcP++;
|
||||
_hopkinsItem[idx]._speedY = *srcP++;
|
||||
}
|
||||
|
||||
_vm->_objectsMan->resetOldFrameIndex();
|
||||
_vm->_objectsMan->resetOldDirection();
|
||||
}
|
||||
|
||||
byte *Globals::allocMemory(int count) {
|
||||
byte *result = (byte *)malloc(count);
|
||||
if (!result)
|
||||
result = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
byte *Globals::freeMemory(byte *p) {
|
||||
if (p)
|
||||
free(p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
251
engines/hopkins/globals.h
Normal file
251
engines/hopkins/globals.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/* 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 HOPKINS_GLOBALS_H
|
||||
#define HOPKINS_GLOBALS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
#include "common/util.h"
|
||||
#include "common/events.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
struct HopkinsItem {
|
||||
int _speedX;
|
||||
int _speedY;
|
||||
};
|
||||
|
||||
struct CharacterLocation {
|
||||
Common::Point _pos;
|
||||
int _startSpriteIndex;
|
||||
int _location;
|
||||
int _zoomFactor;
|
||||
|
||||
void reset() {
|
||||
_pos.x = 0;
|
||||
_pos.y = 0;
|
||||
_startSpriteIndex = 0;
|
||||
_location = 0;
|
||||
_zoomFactor = 0;
|
||||
}
|
||||
|
||||
CharacterLocation() { reset(); }
|
||||
};
|
||||
|
||||
enum SauvegardeOffset {
|
||||
svLastMouseCursor = 1
|
||||
, svLastZoneNum = 2
|
||||
, svLastObjectIndex = 3
|
||||
, svDialogField4 = 4
|
||||
, svLastScreenId = 5
|
||||
, svLastPrevScreenId = 6
|
||||
, svLastInventoryItem = 8
|
||||
, svLastInvMouseCursor = 9
|
||||
, svLastSavegameSlot = 10
|
||||
, svFreedHostageFl = 80
|
||||
, svField94 = 94
|
||||
, svField95 = 95
|
||||
, svForestAvailableFl = 113
|
||||
, svHutBurningFl = 117
|
||||
, svHopkinsCloneFl = 121
|
||||
, svAlternateSpriteFl = 122
|
||||
, svHeavenGuardGoneFl = 123
|
||||
, svField132 = 132
|
||||
, svField133 = 133
|
||||
, svGameWonFl = 135
|
||||
, svCinemaCurtainCond1 = 166
|
||||
, svCinemaCurtainCond2 = 167
|
||||
, svBankAttackAnimPlayedFl = 170
|
||||
, svCopCall1PlayedFl = 171
|
||||
, svCopCall2PlayedFl = 172
|
||||
, svField173 = 173
|
||||
, svField176 = 176
|
||||
, svPoolDogGoneFl = 177
|
||||
, svCinemaDogGoneFl = 181
|
||||
, svField183 = 183
|
||||
, svField184 = 184
|
||||
, svField186 = 186
|
||||
, svField188 = 188
|
||||
, svField200 = 200
|
||||
, svField214 = 214
|
||||
, svBombBoxOpenedFl = 220
|
||||
, svBombDisarmedFl = 225
|
||||
, svField228 = 228
|
||||
, svField231 = 231
|
||||
, svField253 = 253
|
||||
, svField261 = 261
|
||||
, svField270 = 270
|
||||
, svField300 = 300
|
||||
, svBaseElevatorCond1 = 311
|
||||
, svBaseFireFl = 312
|
||||
, svSecondElevatorAvailableFl = 318
|
||||
, svField320 = 320
|
||||
, svEscapeLeftJailFl = 330
|
||||
, svField333 = 333
|
||||
, svField338 = 338
|
||||
, svField339 = 339
|
||||
, svField340 = 340
|
||||
, svField341 = 341
|
||||
, svField352 = 352
|
||||
, svField353 = 353
|
||||
, svField354 = 354
|
||||
, svField355 = 355
|
||||
, svField356 = 356
|
||||
, svField357 = 357
|
||||
, svField399 = 399
|
||||
, svField401 = 401
|
||||
};
|
||||
|
||||
// As Script engine directly access savegame fields,
|
||||
// refactoring it in separated fields properly named is impossible
|
||||
struct Savegame {
|
||||
byte _data[2050];
|
||||
CharacterLocation _cloneHopkins;
|
||||
CharacterLocation _realHopkins;
|
||||
CharacterLocation _samantha;
|
||||
int16 _inventory[35]; // Originally at offset 1300 of data array
|
||||
int16 _mapCarPosX;
|
||||
int16 _mapCarPosY;
|
||||
|
||||
void reset() {
|
||||
for (uint16 i = 0; i < ARRAYSIZE(_data); i++) {
|
||||
_data[i] = 0;
|
||||
}
|
||||
_cloneHopkins.reset();
|
||||
_realHopkins.reset();
|
||||
_samantha.reset();
|
||||
for (uint16 i = 0; i < ARRAYSIZE(_inventory); i++) {
|
||||
_inventory[i] = 0;
|
||||
}
|
||||
_mapCarPosX = 0;
|
||||
_mapCarPosY = 0;
|
||||
}
|
||||
|
||||
Savegame() { reset(); }
|
||||
};
|
||||
|
||||
struct CreditItem {
|
||||
bool _actvFl;
|
||||
int _color;
|
||||
int _linePosY;
|
||||
int _lineSize;
|
||||
byte _line[50];
|
||||
};
|
||||
|
||||
enum Language { LANG_EN = 0, LANG_FR = 1, LANG_SP = 2};
|
||||
|
||||
enum PlayerCharacter { CHARACTER_HOPKINS = 0, CHARACTER_HOPKINS_CLONE = 1, CHARACTER_SAMANTHA = 2 };
|
||||
|
||||
enum Directions {
|
||||
DIR_NONE = -1,
|
||||
DIR_UP = 1,
|
||||
DIR_UP_RIGHT = 2,
|
||||
DIR_RIGHT = 3,
|
||||
DIR_DOWN_RIGHT = 4,
|
||||
DIR_DOWN = 5,
|
||||
DIR_DOWN_LEFT = 6,
|
||||
DIR_LEFT = 7,
|
||||
DIR_UP_LEFT = 8
|
||||
};
|
||||
|
||||
enum EventMode {
|
||||
EVENTMODE_DEFAULT = 0,
|
||||
EVENTMODE_IGNORE = 1,
|
||||
EVENTMODE_CREDITS = 3,
|
||||
EVENTMODE_ALT = 4
|
||||
};
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
/**
|
||||
* Engine Globals
|
||||
*/
|
||||
class Globals {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
public:
|
||||
bool _disableInventFl;
|
||||
bool _cityMapEnabledFl;
|
||||
bool _linuxEndDemoFl;
|
||||
bool _censorshipFl;
|
||||
bool _introSpeechOffFl;
|
||||
int _exitId;
|
||||
Directions _oceanDirection;
|
||||
int _actionDirection;
|
||||
int _inventory[36];
|
||||
int _screenId;
|
||||
int _prevScreenId;
|
||||
int _characterMaxPosY;
|
||||
int _baseMapColor;
|
||||
int _spriteSize[500];
|
||||
PlayerCharacter _characterType;
|
||||
uint _speed;
|
||||
byte *_answerBuffer;
|
||||
Savegame *_saveData;
|
||||
Language _language;
|
||||
HopkinsItem _hopkinsItem[70];
|
||||
|
||||
CreditItem _creditsItem[200];
|
||||
int _creditsLineNumb;
|
||||
int _creditsStep;
|
||||
int _creditsPosY;
|
||||
int _creditsStartX;
|
||||
int _creditsEndX;
|
||||
int _creditsStartY;
|
||||
int _creditsEndY;
|
||||
|
||||
int _menuSpeed;
|
||||
int _menuSoundOff;
|
||||
int _menuTextOff;
|
||||
int _menuVoiceOff;
|
||||
int _menuMusicOff;
|
||||
int _menuDisplayType;
|
||||
int _menuScrollSpeed;
|
||||
|
||||
byte *_optionDialogSpr;
|
||||
bool _optionDialogFl;
|
||||
|
||||
bool _actionMoveTo;
|
||||
bool _freezeCharacterFl;
|
||||
bool _checkDistanceFl;
|
||||
byte *_characterSpriteBuf;
|
||||
Common::Path _zoneFilename;
|
||||
Common::Path _textFilename;
|
||||
byte *_levelSpriteBuf;
|
||||
|
||||
EventMode _eventMode;
|
||||
|
||||
Globals(HopkinsEngine *vm);
|
||||
~Globals();
|
||||
byte *allocMemory(int count);
|
||||
byte *freeMemory(byte *p);
|
||||
void setConfig();
|
||||
void clearAll();
|
||||
void loadCharacterData();
|
||||
|
||||
int _curRoomNum;
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_GLOBALS_H */
|
||||
1936
engines/hopkins/graphics.cpp
Normal file
1936
engines/hopkins/graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
192
engines/hopkins/graphics.h
Normal file
192
engines/hopkins/graphics.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/* 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 HOPKINS_GRAPHICS_H
|
||||
#define HOPKINS_GRAPHICS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/path.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
constexpr int DIRTY_RECTS_SIZE = 250;
|
||||
constexpr int PALETTE_SIZE = 256;
|
||||
constexpr int PALETTE_BLOCK_SIZE = (PALETTE_SIZE * 3);
|
||||
constexpr int PALETTE_EXT_BLOCK_SIZE = 800;
|
||||
static const byte kSetOffset = 251;
|
||||
static const byte kByteStop = 252;
|
||||
static const byte k8bVal = 253;
|
||||
static const byte k16bVal = 254;
|
||||
|
||||
struct RGB8 {
|
||||
byte r;
|
||||
byte g;
|
||||
byte b;
|
||||
};
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
class GraphicsManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
int _lockCounter;
|
||||
bool _initGraphicsFl;
|
||||
int _screenWidth;
|
||||
int _screenHeight;
|
||||
byte *_videoPtr;
|
||||
int _width;
|
||||
int _posXClipped, _posYClipped;
|
||||
bool _clipFl;
|
||||
int _specialWidth;
|
||||
|
||||
int _enlargedX, _enlargedY;
|
||||
bool _enlargedXFl, _enlargedYFl;
|
||||
int _clipX1, _clipY1;
|
||||
int _reduceX, _reducedY;
|
||||
int _zoomOutFactor;
|
||||
|
||||
bool _manualScroll;
|
||||
|
||||
void loadScreen(const Common::Path &file);
|
||||
void loadPCX640(byte *surface, const Common::Path &file, byte *palette, bool typeFlag);
|
||||
void loadPCX320(byte *surface, const Common::Path &file, byte *palette);
|
||||
void fadeIn(const byte *palette, int step, const byte *surface);
|
||||
void fadeOut(const byte *palette, int step, const byte *surface);
|
||||
void changePalette(const byte *palette);
|
||||
uint16 mapRGB(byte r, byte g, byte b);
|
||||
void copy16bFromSurfaceScaleX2(const byte *surface);
|
||||
|
||||
void translateSurface(byte *destP, const byte *srcP, int count, int minThreshold, int maxThreshold);
|
||||
void displayScaled8BitRect(const byte *surface, int xp, int yp, int width, int height, int destX, int destY);
|
||||
|
||||
void lockScreen();
|
||||
void unlockScreen();
|
||||
public:
|
||||
byte _paletteBuffer[PALETTE_SIZE * 2];
|
||||
byte _colorTable[PALETTE_EXT_BLOCK_SIZE];
|
||||
byte _palette[PALETTE_EXT_BLOCK_SIZE];
|
||||
byte _oldPalette[PALETTE_EXT_BLOCK_SIZE];
|
||||
byte *_backBuffer;
|
||||
byte *_frontBuffer;
|
||||
byte *_screenBuffer;
|
||||
byte *_backupScreen;
|
||||
bool _largeScreenFl;
|
||||
bool _noFadingFl;
|
||||
bool _fadingFl;
|
||||
bool _skipVideoLockFl;
|
||||
int _scrollOffset;
|
||||
int _scrollPosX;
|
||||
int _oldScrollPosX;
|
||||
int _scrollSpeed;
|
||||
int _lineNbr;
|
||||
int _lineNbr2;
|
||||
int _minX, _minY;
|
||||
int _maxX, _maxY;
|
||||
int _scrollStatus;
|
||||
int _fadeDefaultSpeed;
|
||||
int _screenLineSize;
|
||||
|
||||
/**
|
||||
* The _dirtyRects list contains paletted game areas that need to be redrawn.
|
||||
* The _dstrect array is the list of areas of the screen that ScummVM needs to be redrawn.
|
||||
* Some areas, such as the animation managers, skip the _dirtyRects and use _dstrec directly.
|
||||
*/
|
||||
Common::Array<Common::Rect> _dirtyRects;
|
||||
Common::Array<Common::Rect> _refreshRects;
|
||||
bool _showDirtyRects;
|
||||
bool _showZones;
|
||||
bool _showLines;
|
||||
|
||||
byte *_palettePixels;
|
||||
public:
|
||||
GraphicsManager(HopkinsEngine *vm);
|
||||
~GraphicsManager();
|
||||
|
||||
void clearPalette();
|
||||
void clearScreen();
|
||||
void clearVesaScreen();
|
||||
void resetDirtyRects();
|
||||
void resetRefreshRects();
|
||||
void addDirtyRect(int x1, int y1, int x2, int y2);
|
||||
void addDirtyRect(const Common::Rect &r) { addDirtyRect(r.left, r.top, r.right, r.bottom); }
|
||||
void addRefreshRect(int x1, int y1, int x2, int y2);
|
||||
void addRectToArray(Common::Array<Common::Rect> &rects, const Common::Rect &newRect);
|
||||
void displayDirtyRects();
|
||||
void displayRefreshRects();
|
||||
void displayZones();
|
||||
void displayLines();
|
||||
void displayDebugRect(Graphics::Surface *surface, const Common::Rect &srcRect, uint32 color = 0xffffff);
|
||||
void copySurface(const byte *surface, int x1, int y1, int width, int height, byte *destSurface, int destX, int destY);
|
||||
void loadImage(const Common::Path &file);
|
||||
void loadVgaImage(const Common::Path &file);
|
||||
void fadeInLong();
|
||||
void fadeInBreakout();
|
||||
void fadeInDefaultLength(const byte *surface);
|
||||
void fadeInShort();
|
||||
void fadeOutDefaultLength(const byte *surface);
|
||||
void fadeOutBreakout();
|
||||
void fadeOutLong();
|
||||
void fadeOutShort();
|
||||
void copyWinscanVbe3(const byte *srcData, byte *destSurface);
|
||||
void copyWinscanVbe(const byte *srcP, byte *destP);
|
||||
void copyVideoVbe16(const byte *srcData);
|
||||
void copyVideoVbe16a(const byte *srcData);
|
||||
void copySurfaceRect(const byte *srcSurface, byte *destSurface, int xs, int ys, int width, int height);
|
||||
void restoreSurfaceRect(byte *destSurface, const byte *src, int xp, int yp, int width, int height);
|
||||
void displayFont(byte *surface, const byte *spriteData, int xp, int yp, int characterIndex, int color);
|
||||
void drawHorizontalLine(byte *surface, int xp, int yp, uint16 width, byte col);
|
||||
void drawVerticalLine(byte *surface, int xp, int yp, int height, byte col);
|
||||
void initColorTable(int minIndex, int maxIndex, byte *palette);
|
||||
void setGraphicalMode(int width, int height);
|
||||
void setPaletteVGA256(const byte *palette);
|
||||
void setPaletteVGA256WithRefresh(const byte *palette, const byte *surface);
|
||||
void scrollScreen(int amount);
|
||||
int zoomIn(int v, int percentage);
|
||||
int zoomOut(int v, int percentage);
|
||||
void initScreen(const Common::Path &file, int mode, bool initializeScreen);
|
||||
void displayAllBob();
|
||||
void endDisplayBob();
|
||||
void updateScreen();
|
||||
void reduceScreenPart(const byte *srcSruface, byte *destSurface, int xp, int yp, int width, int height, int zoom);
|
||||
void setScreenWidth(int pitch);
|
||||
|
||||
void setColorPercentage(int palIndex, int r, int g, int b);
|
||||
void setColorPercentage2(int palIndex, int r, int g, int b);
|
||||
void fastDisplay(const byte *spriteData, int xp, int yp, int spriteIndex, bool addSegment = true);
|
||||
void fastDisplay2(const byte *objectData, int xp, int yp, int idx, bool addSegment = true);
|
||||
void drawCompressedSprite(byte *surface, const byte *srcData, int xp300, int yp300, int frameIndex, int zoom1, int zoom2, bool flipFl);
|
||||
void copyRect(const byte *srcSurface, int x1, int y1, uint16 width, int height, byte *destSurface, int destX, int destY);
|
||||
void drawVesaSprite(byte *surface, const byte *spriteData, int xp, int yp, int spriteIndex);
|
||||
void display8BitRect(const byte *surface, int xs, int ys, int width, int height, int destX, int destY);
|
||||
void fillSurface(byte *surface, byte *col, int size);
|
||||
void displayScreen(bool initPalette);
|
||||
void backupScreen();
|
||||
void restoreScreen();
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_GRAPHICS_H */
|
||||
2925
engines/hopkins/hopkins.cpp
Normal file
2925
engines/hopkins/hopkins.cpp
Normal file
File diff suppressed because it is too large
Load Diff
192
engines/hopkins/hopkins.h
Normal file
192
engines/hopkins/hopkins.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/* 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 HOPKINS_HOPKINS_H
|
||||
#define HOPKINS_HOPKINS_H
|
||||
|
||||
#include "hopkins/anim.h"
|
||||
#include "hopkins/computer.h"
|
||||
#include "hopkins/debugger.h"
|
||||
#include "hopkins/dialogs.h"
|
||||
#include "hopkins/events.h"
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/font.h"
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/graphics.h"
|
||||
#include "hopkins/lines.h"
|
||||
#include "hopkins/menu.h"
|
||||
#include "hopkins/objects.h"
|
||||
#include "hopkins/saveload.h"
|
||||
#include "hopkins/script.h"
|
||||
#include "hopkins/sound.h"
|
||||
#include "hopkins/talk.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "common/error.h"
|
||||
#include "common/random.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/util.h"
|
||||
#include "engines/engine.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
/**
|
||||
* This is the namespace of the Hopkins engine.
|
||||
*
|
||||
* Status of this engine: In Development
|
||||
*
|
||||
* Games using this engine:
|
||||
* - Hopkins FBI
|
||||
*/
|
||||
namespace Hopkins {
|
||||
|
||||
#define SCREEN_WIDTH 640
|
||||
#define SCREEN_HEIGHT 480
|
||||
|
||||
enum HOPKINSAction {
|
||||
kActionNone,
|
||||
kActionEscape,
|
||||
kActionInventory,
|
||||
kActionSave,
|
||||
kActionLoad,
|
||||
kActionOptions
|
||||
};
|
||||
|
||||
enum HopkinsDebugChannels {
|
||||
kDebugPath = 1,
|
||||
kDebugGraphics,
|
||||
};
|
||||
|
||||
/**
|
||||
* A wrapper macro used around three character constants, like 'END', to
|
||||
* ensure portability. Typical usage: MKTAG24('E','N','D').
|
||||
*/
|
||||
#define MKTAG24(a0,a1,a2) ((uint32)((a2) | (a1) << 8 | ((a0) << 16)))
|
||||
|
||||
struct HopkinsGameDescription;
|
||||
|
||||
class HopkinsEngine : public Engine {
|
||||
private:
|
||||
const HopkinsGameDescription *_gameDescription;
|
||||
Common::RandomSource _randomSource;
|
||||
|
||||
void initializeSystem();
|
||||
|
||||
void displayNotAvailable();
|
||||
void restoreSystem();
|
||||
void endLinuxDemo();
|
||||
void displayEndDemo();
|
||||
void bombExplosion();
|
||||
void handleConflagration();
|
||||
void playSubmarineCutscene();
|
||||
void playUnderwaterBaseCutscene();
|
||||
void playPlaneCutscene();
|
||||
void playEnding();
|
||||
bool isUnderwaterSubScene();
|
||||
|
||||
/**
|
||||
* Displays the map screen in the underground base.
|
||||
*/
|
||||
int handleBaseMap();
|
||||
|
||||
/**
|
||||
* Loads the base map from the PBASE file
|
||||
*/
|
||||
void loadBaseMap();
|
||||
|
||||
/**
|
||||
* Draws a simple base map for the Windows version, which implemented a 'Wolfenstein 3D'
|
||||
* style shooter for the base, rather than having a map
|
||||
*/
|
||||
void drawBaseMap();
|
||||
|
||||
void handleOceanMouseEvents();
|
||||
void setSubmarineSprites();
|
||||
void handleOceanMaze(int16 curExitId, const Common::Path &backgroundFilename, Directions defaultDirection, int16 exit1, int16 exit2, int16 exit3, int16 exit4, int16 soundId);
|
||||
void loadCredits();
|
||||
void displayCredits(int startPosY, byte *buffer, char color);
|
||||
void displayCredits();
|
||||
void handleNotAvailable(int nextScreen);
|
||||
|
||||
bool runWin95Demo();
|
||||
bool runLinuxDemo();
|
||||
bool runFull();
|
||||
|
||||
/**
|
||||
* Show warning screen about the game being adults only.
|
||||
*/
|
||||
bool displayAdultDisclaimer();
|
||||
protected:
|
||||
// Engine APIs
|
||||
Common::Error run() override;
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
|
||||
public:
|
||||
AnimationManager *_animMan;
|
||||
ComputerManager *_computer;
|
||||
DialogsManager *_dialog;
|
||||
EventsManager *_events;
|
||||
FileManager *_fileIO;
|
||||
FontManager *_fontMan;
|
||||
Globals *_globals;
|
||||
GraphicsManager *_graphicsMan;
|
||||
LinesManager *_linesMan;
|
||||
MenuManager *_menuMan;
|
||||
ObjectsManager *_objectsMan;
|
||||
SaveLoadManager *_saveLoad;
|
||||
ScriptManager *_script;
|
||||
SoundManager *_soundMan;
|
||||
TalkManager *_talkMan;
|
||||
|
||||
public:
|
||||
HopkinsEngine(OSystem *syst, const HopkinsGameDescription *gameDesc);
|
||||
~HopkinsEngine() override;
|
||||
void GUIError(const Common::String &msg);
|
||||
|
||||
uint32 getFeatures() const;
|
||||
Common::Language getLanguage() const;
|
||||
Common::Platform getPlatform() const;
|
||||
uint16 getVersion() const;
|
||||
bool getIsDemo() const;
|
||||
const Common::String &getTargetName() const;
|
||||
|
||||
int getRandomNumber(int maxNumber);
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
|
||||
int _startGameSlot;
|
||||
|
||||
/**
|
||||
* Run the introduction sequence
|
||||
*/
|
||||
void playIntro();
|
||||
|
||||
/**
|
||||
* Synchronizes the sound settings from ScummVM into the engine
|
||||
*/
|
||||
void syncSoundSettings() override;
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_HOPKINS_H */
|
||||
2952
engines/hopkins/lines.cpp
Normal file
2952
engines/hopkins/lines.cpp
Normal file
File diff suppressed because it is too large
Load Diff
197
engines/hopkins/lines.h
Normal file
197
engines/hopkins/lines.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/* 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 HOPKINS_LINES_H
|
||||
#define HOPKINS_LINES_H
|
||||
|
||||
#include "hopkins/globals.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
struct LigneZoneItem {
|
||||
int _count;
|
||||
int _bobZoneIdx;
|
||||
int16 *_zoneData;
|
||||
};
|
||||
|
||||
#define INVALID_LINE_VALUE 1300
|
||||
|
||||
#define MAX_LINES 400
|
||||
|
||||
struct RouteItem;
|
||||
|
||||
struct LigneItem {
|
||||
int _lineDataEndIdx;
|
||||
Directions _direction;
|
||||
Directions _directionRouteInc;
|
||||
Directions _directionRouteDec;
|
||||
int16 *_lineData;
|
||||
|
||||
int appendToRouteInc(int from, int to, RouteItem *route, int index);
|
||||
int appendToRouteDec(int from, int to, RouteItem *route, int index);
|
||||
};
|
||||
|
||||
struct SmoothItem {
|
||||
int _posX;
|
||||
int _posY;
|
||||
};
|
||||
|
||||
struct SegmentItem {
|
||||
int _minZoneLineIdx;
|
||||
int _maxZoneLineIdx;
|
||||
};
|
||||
|
||||
struct SquareZoneItem {
|
||||
bool _enabledFl;
|
||||
int _left;
|
||||
int _right;
|
||||
int _top;
|
||||
int _bottom;
|
||||
int _minZoneLineIdx;
|
||||
int _maxZoneLineIdx;
|
||||
bool _squareZoneFl;
|
||||
};
|
||||
|
||||
struct ZoneItem {
|
||||
int _destX;
|
||||
int _destY;
|
||||
int _spriteIndex;
|
||||
int _verbFl1;
|
||||
int _verbFl2;
|
||||
int _verbFl3;
|
||||
int _verbFl4;
|
||||
int _verbFl5;
|
||||
int _verbFl6;
|
||||
int _verbFl7;
|
||||
int _verbFl8;
|
||||
int _verbFl9;
|
||||
int _verbFl10;
|
||||
bool _enabledFl;
|
||||
int _messageId;
|
||||
};
|
||||
|
||||
struct RouteItem {
|
||||
int16 _x;
|
||||
int16 _y;
|
||||
Directions _dir;
|
||||
bool isValid() const { return _x != -1 || _y != -1; }
|
||||
void invalidate() { _x = _y = -1; _dir = DIR_NONE; }
|
||||
void set(int16 X, int16 Y, Directions dir) { _x = X; _y = Y; _dir = dir; }
|
||||
};
|
||||
|
||||
|
||||
class LinesManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
bool _forceHideText;
|
||||
int _hotspotTextColor;
|
||||
int _pathFindingMaxDepth;
|
||||
SmoothItem _smoothRoute[4000];
|
||||
Directions _smoothMoveDirection;
|
||||
LigneZoneItem _zoneLine[MAX_LINES+1];
|
||||
SegmentItem _segment[101];
|
||||
int _currentSegmentId;
|
||||
int _maxLineIdx;
|
||||
int _lastLine;
|
||||
int _newLineIdx;
|
||||
int _newLineDataIdx;
|
||||
int _newRouteIdx;
|
||||
int _newPosX;
|
||||
int _newPosY;
|
||||
int _oldMouseX, _oldMouseY;
|
||||
int _oldRouteFromX;
|
||||
int _oldRouteFromY;
|
||||
int _oldRouteDestX;
|
||||
int _oldRouteDestY;
|
||||
int _oldZoneNum;
|
||||
|
||||
byte *_largeBuf;
|
||||
RouteItem *_testRoute0;
|
||||
RouteItem *_testRoute1;
|
||||
int16 *_lineBuf;
|
||||
RouteItem _bestRoute[8001];
|
||||
int _zoneSkipCount;
|
||||
int _oldMouseZoneId;
|
||||
|
||||
int avoidObstacle(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route);
|
||||
int avoidObstacleOnSegment(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route, int startLineIdx, int endLineIdx);
|
||||
int checkInventoryHotspotsRow(int posX, int minZoneNum, bool lastRow);
|
||||
void removeZoneLine(int idx);
|
||||
void removeLine(int idx);
|
||||
int checkCollision(int xp, int yp);
|
||||
bool checkCollisionLine(int xp, int yp, int *foundDataIdx, int *foundLineIdx, int startLineIdx, int endLineIdx);
|
||||
bool checkSmoothMove(int fromX, int fromY, int destX, int destY);
|
||||
bool makeSmoothMove(int fromX, int fromY, int destX, int destY);
|
||||
int characterRoute(int fromX, int fromY, int destX, int destY, int startLineIdx, int endLineIdx, int routeIdx);
|
||||
int testLine(int paramX, int paramY, int *testValue, int *foundLineIdx, int *foundDataIdx);
|
||||
void useRoute0(int idx, int curRouteIdx);
|
||||
void useRoute1(int idx, int curRouteIdx);
|
||||
void useRoute2(int idx, int curRouteIdx);
|
||||
int computeYSteps(int idx);
|
||||
int computeRouteIdx(int lineIdx, int dataIdx, int fromX, int fromY, int destX, int destY, int routerIdx, RouteItem *route);
|
||||
|
||||
bool MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, int routeIdx);
|
||||
bool PLAN_TEST(int paramX, int paramY, int superRouteIdx, int paramStartLineIdx, int paramEndLineIdx);
|
||||
|
||||
public:
|
||||
RouteItem *_route;
|
||||
RouteItem *_testRoute2;
|
||||
|
||||
int _bobZone[105];
|
||||
bool _bobZoneFl[105];
|
||||
ZoneItem _zone[106];
|
||||
SquareZoneItem _squareZone[101];
|
||||
LigneItem _lineItem[MAX_LINES];
|
||||
int _linesNumb;
|
||||
|
||||
LinesManager(HopkinsEngine *vm);
|
||||
~LinesManager();
|
||||
void clearAll();
|
||||
|
||||
void setMaxLineIdx(int idx);
|
||||
int checkInventoryHotspots(int posX, int posY);
|
||||
void addZoneLine(int idx, int fromX, int fromY, int destX, int destY, int bobZoneIdx);
|
||||
void loadLines(const Common::Path &file);
|
||||
void addLine(int lineIdx, Directions direction, int fromX, int fromY, int destX, int destY);
|
||||
void initRoute();
|
||||
RouteItem *findRoute(int fromX, int fromY, int destX, int destY);
|
||||
RouteItem *cityMapCarRoute(int x1, int y1, int x2, int y2);
|
||||
void clearAllZones();
|
||||
void initSquareZones();
|
||||
void resetLines();
|
||||
void resetLinesNumb();
|
||||
void resetLastLine();
|
||||
void enableZone(int idx);
|
||||
void disableZone(int idx);
|
||||
void checkZone();
|
||||
int getMouseZone();
|
||||
void optimizeRoute(RouteItem *route);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_FONT_H */
|
||||
185
engines/hopkins/menu.cpp
Normal file
185
engines/hopkins/menu.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/* 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 "hopkins/menu.h"
|
||||
|
||||
#include "hopkins/dialogs.h"
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/events.h"
|
||||
#include "hopkins/graphics.h"
|
||||
#include "hopkins/sound.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/events.h"
|
||||
#include "common/file.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
enum MenuSelection { MENU_NONE = 0, PLAY_GAME = 1, LOAD_GAME = 2, OPTIONS = 3, INTRODUCTION = 4, QUIT = 5 };
|
||||
|
||||
MenuManager::MenuManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
}
|
||||
|
||||
int MenuManager::menu() {
|
||||
byte *spriteData = nullptr;
|
||||
MenuSelection menuIndex;
|
||||
Common::Point mousePos;
|
||||
signed int result;
|
||||
int frameIndex[] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
if (_vm->shouldQuit())
|
||||
return -1;
|
||||
|
||||
result = 0;
|
||||
while (!_vm->shouldQuit()) {
|
||||
_vm->_objectsMan->_forestFl = false;
|
||||
_vm->_events->_breakoutFl = false;
|
||||
_vm->_globals->_disableInventFl = true;
|
||||
_vm->_globals->_exitId = 0;
|
||||
|
||||
for (int idx = 0; idx < 31; ++idx)
|
||||
_vm->_globals->_inventory[idx] = 0;
|
||||
|
||||
memset(_vm->_globals->_saveData->_data, 0, 2050-50);
|
||||
_vm->_objectsMan->addObject(14);
|
||||
memset(frameIndex, 0, sizeof(int) * ARRAYSIZE(frameIndex));
|
||||
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
|
||||
_vm->_graphicsMan->loadImage("MENU");
|
||||
else {
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_EN:
|
||||
_vm->_graphicsMan->loadImage("MENUAN");
|
||||
break;
|
||||
case LANG_FR:
|
||||
_vm->_graphicsMan->loadImage("MENUFR");
|
||||
break;
|
||||
case LANG_SP:
|
||||
_vm->_graphicsMan->loadImage("MENUES");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphicsMan->fadeInLong();
|
||||
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
|
||||
spriteData = _vm->_objectsMan->loadSprite("MENU.SPR");
|
||||
else {
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_EN:
|
||||
spriteData = _vm->_objectsMan->loadSprite("MENUAN.SPR");
|
||||
break;
|
||||
case LANG_FR:
|
||||
spriteData = _vm->_objectsMan->loadSprite("MENUFR.SPR");
|
||||
break;
|
||||
case LANG_SP:
|
||||
spriteData = _vm->_objectsMan->loadSprite("MENUES.SPR");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_events->mouseOn();
|
||||
_vm->_events->changeMouseCursor(0);
|
||||
_vm->_events->_mouseCursorId = 0;
|
||||
_vm->_events->_mouseSpriteId = 0;
|
||||
|
||||
_vm->_soundMan->playSound(28);
|
||||
|
||||
// Loop to make menu selection
|
||||
bool selectionMade = false;
|
||||
do {
|
||||
if (_vm->shouldQuit())
|
||||
return -1;
|
||||
|
||||
menuIndex = MENU_NONE;
|
||||
mousePos = Common::Point(_vm->_events->getMouseX(), _vm->_events->getMouseY());
|
||||
|
||||
if (mousePos.x >= 232 && mousePos.x <= 408) {
|
||||
if (mousePos.y >= 261 && mousePos.y <= 284)
|
||||
menuIndex = PLAY_GAME;
|
||||
else if (mousePos.y >= 293 && mousePos.y <= 316)
|
||||
menuIndex = LOAD_GAME;
|
||||
else if (mousePos.y >= 325 && mousePos.y <= 347)
|
||||
menuIndex = OPTIONS;
|
||||
else if (mousePos.y >= 356 && mousePos.y <= 379)
|
||||
menuIndex = INTRODUCTION;
|
||||
else if (mousePos.y >= 388 && mousePos.y <= 411)
|
||||
menuIndex = QUIT;
|
||||
}
|
||||
|
||||
memset(frameIndex, 0, sizeof(int) * ARRAYSIZE(frameIndex));
|
||||
if (menuIndex > MENU_NONE)
|
||||
frameIndex[menuIndex - 1] = 1;
|
||||
|
||||
_vm->_graphicsMan->fastDisplay(spriteData, 230, 259, frameIndex[0]);
|
||||
_vm->_graphicsMan->fastDisplay(spriteData, 230, 291, frameIndex[1] + 2);
|
||||
_vm->_graphicsMan->fastDisplay(spriteData, 230, 322, frameIndex[2] + 4);
|
||||
_vm->_graphicsMan->fastDisplay(spriteData, 230, 354, frameIndex[3] + 6);
|
||||
_vm->_graphicsMan->fastDisplay(spriteData, 230, 386, frameIndex[4] + 8);
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
|
||||
if (_vm->_events->getMouseButton() == 1 && menuIndex != MENU_NONE)
|
||||
selectionMade = true;
|
||||
} while (!selectionMade);
|
||||
|
||||
if (menuIndex > MENU_NONE) {
|
||||
_vm->_graphicsMan->fastDisplay(spriteData, 230, 259 + 32 * (menuIndex - 1), 10 + (menuIndex - 1));
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
_vm->_events->delay(200);
|
||||
}
|
||||
|
||||
if (menuIndex == PLAY_GAME) {
|
||||
result = 1;
|
||||
break;
|
||||
} else if (menuIndex == LOAD_GAME) {
|
||||
_vm->_globals->_exitId = -1;
|
||||
_vm->_dialog->showLoadGame();
|
||||
|
||||
if (_vm->_globals->_exitId != -1) {
|
||||
result = _vm->_globals->_exitId;
|
||||
break;
|
||||
}
|
||||
_vm->_globals->_exitId = 0;
|
||||
} else if (menuIndex == OPTIONS) {
|
||||
_vm->_dialog->showOptionsDialog();
|
||||
} else if (menuIndex == INTRODUCTION) {
|
||||
_vm->playIntro();
|
||||
} else if (menuIndex == QUIT) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_globals->freeMemory(spriteData);
|
||||
_vm->_globals->_disableInventFl = false;
|
||||
_vm->_graphicsMan->fadeOutLong();
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
45
engines/hopkins/menu.h
Normal file
45
engines/hopkins/menu.h
Normal 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 HOPKINS_MENU_H
|
||||
#define HOPKINS_MENU_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "common/error.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
class MenuManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
public:
|
||||
MenuManager(HopkinsEngine *vm);
|
||||
|
||||
int menu();
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_MENU_H */
|
||||
268
engines/hopkins/metaengine.cpp
Normal file
268
engines/hopkins/metaengine.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
/* 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 "hopkins/hopkins.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/str-array.h"
|
||||
#include "common/translation.h"
|
||||
#include "common/memstream.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "common/system.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
#include "hopkins/detection.h"
|
||||
|
||||
#define MAX_SAVES 99
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
{
|
||||
GAMEOPTION_GORE_DEFAULT_OFF,
|
||||
{
|
||||
_s("Gore Mode"),
|
||||
_s("Enable Gore Mode when available"),
|
||||
"enable_gore",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
GAMEOPTION_GORE_DEFAULT_ON,
|
||||
{
|
||||
_s("Gore Mode"),
|
||||
_s("Enable Gore Mode when available"),
|
||||
"enable_gore",
|
||||
true,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
uint32 HopkinsEngine::getFeatures() const {
|
||||
return _gameDescription->desc.flags;
|
||||
}
|
||||
|
||||
Common::Language HopkinsEngine::getLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
Common::Platform HopkinsEngine::getPlatform() const {
|
||||
return _gameDescription->desc.platform;
|
||||
}
|
||||
|
||||
bool HopkinsEngine::getIsDemo() const {
|
||||
return _gameDescription->desc.flags & ADGF_DEMO;
|
||||
}
|
||||
|
||||
const Common::String &HopkinsEngine::getTargetName() const {
|
||||
return _targetName;
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
class HopkinsMetaEngine : public AdvancedMetaEngine<Hopkins::HopkinsGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "hopkins";
|
||||
}
|
||||
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
|
||||
return Hopkins::optionsList;
|
||||
}
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const Hopkins::HopkinsGameDescription *desc) const override;
|
||||
|
||||
SaveStateList listSaves(const char *target) const override;
|
||||
int getMaximumSaveSlot() const override;
|
||||
bool removeSaveState(const char *target, int slot) const override;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
};
|
||||
|
||||
bool HopkinsMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSimpleSavesNames);
|
||||
}
|
||||
|
||||
bool Hopkins::HopkinsEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
Common::Error HopkinsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Hopkins::HopkinsGameDescription *desc) const {
|
||||
*engine = new Hopkins::HopkinsEngine(syst,desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
SaveStateList HopkinsMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::String saveDesc;
|
||||
Common::String pattern = Common::String::format("%s.0##", target);
|
||||
Common::StringArray filenames = saveFileMan->listSavefiles(pattern);
|
||||
|
||||
Hopkins::hopkinsSavegameHeader header;
|
||||
SaveStateList saveList;
|
||||
|
||||
for (const auto &filename : filenames) {
|
||||
const char *ext = strrchr(filename.c_str(), '.');
|
||||
int slot = ext ? atoi(ext + 1) : -1;
|
||||
|
||||
if (slot >= 0 && slot < MAX_SAVES) {
|
||||
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename);
|
||||
|
||||
if (in) {
|
||||
if (Hopkins::SaveLoadManager::readSavegameHeader(in, header)) {
|
||||
saveList.push_back(SaveStateDescriptor(this, slot, header._saveName));
|
||||
}
|
||||
|
||||
delete in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort saves based on slot number.
|
||||
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
|
||||
return saveList;
|
||||
}
|
||||
|
||||
int HopkinsMetaEngine::getMaximumSaveSlot() const {
|
||||
return MAX_SAVES;
|
||||
}
|
||||
|
||||
bool HopkinsMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String filename = Common::String::format("%s.%03d", target, slot);
|
||||
return g_system->getSavefileManager()->removeSavefile(filename);
|
||||
}
|
||||
|
||||
SaveStateDescriptor HopkinsMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::String filename = Common::String::format("%s.%03d", target, slot);
|
||||
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
|
||||
|
||||
if (f) {
|
||||
Hopkins::hopkinsSavegameHeader header;
|
||||
if (!Hopkins::SaveLoadManager::readSavegameHeader(f, header, false)) {
|
||||
delete f;
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
delete f;
|
||||
|
||||
// Create the return descriptor
|
||||
SaveStateDescriptor desc(this, slot, header._saveName);
|
||||
desc.setThumbnail(header._thumbnail);
|
||||
desc.setSaveDate(header._year, header._month, header._day);
|
||||
desc.setSaveTime(header._hour, header._minute);
|
||||
desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
Common::KeymapArray HopkinsMetaEngine::initKeymaps(const char *target) const {
|
||||
using namespace Common;
|
||||
using namespace Hopkins;
|
||||
|
||||
Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "hopkins-default", _("Default keymappings"));
|
||||
Keymap *gameKeyMap = new Keymap(Keymap::kKeymapTypeGame, "game-shortcuts", _("Game keymappings"));
|
||||
|
||||
Action *act;
|
||||
|
||||
act = new Action(kStandardActionLeftClick, _("Left click"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Right click"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("ESCAPE", _("Exit / Skip"));
|
||||
act->setCustomEngineActionEvent(kActionEscape);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_BACK");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("INVENTORY", _("Open inventory"));
|
||||
act->setCustomEngineActionEvent(kActionInventory);
|
||||
act->addDefaultInputMapping("i");
|
||||
act->addDefaultInputMapping("TAB");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Save game"));
|
||||
act->setCustomEngineActionEvent(kActionSave);
|
||||
act->addDefaultInputMapping("F5");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Load game"));
|
||||
act->setCustomEngineActionEvent(kActionLoad);
|
||||
act->addDefaultInputMapping("F7");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("OPTIONS", _("Options menu"));
|
||||
act->setCustomEngineActionEvent(kActionOptions);
|
||||
act->addDefaultInputMapping("o");
|
||||
act->addDefaultInputMapping("F1");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
|
||||
|
||||
KeymapArray keymaps(2);
|
||||
keymaps[0] = engineKeyMap;
|
||||
keymaps[1] = gameKeyMap;
|
||||
|
||||
return keymaps;
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(HOPKINS)
|
||||
REGISTER_PLUGIN_DYNAMIC(HOPKINS, PLUGIN_TYPE_ENGINE, HopkinsMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(HOPKINS, PLUGIN_TYPE_ENGINE, HopkinsMetaEngine);
|
||||
#endif
|
||||
32
engines/hopkins/module.mk
Normal file
32
engines/hopkins/module.mk
Normal file
@@ -0,0 +1,32 @@
|
||||
MODULE := engines/hopkins
|
||||
|
||||
MODULE_OBJS := \
|
||||
anim.o \
|
||||
computer.o \
|
||||
debugger.o \
|
||||
dialogs.o \
|
||||
events.o \
|
||||
files.o \
|
||||
font.o \
|
||||
graphics.o \
|
||||
globals.o \
|
||||
hopkins.o \
|
||||
lines.o \
|
||||
menu.o \
|
||||
metaengine.o \
|
||||
objects.o \
|
||||
saveload.o \
|
||||
script.o \
|
||||
sound.o \
|
||||
talk.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_HOPKINS), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
4084
engines/hopkins/objects.cpp
Normal file
4084
engines/hopkins/objects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
337
engines/hopkins/objects.h
Normal file
337
engines/hopkins/objects.h
Normal file
@@ -0,0 +1,337 @@
|
||||
/* 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 HOPKINS_OBJECTS_H
|
||||
#define HOPKINS_OBJECTS_H
|
||||
|
||||
#include "hopkins/globals.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#define MAX_SPRITE 5
|
||||
namespace Hopkins {
|
||||
|
||||
struct ObjectAuthIcon {
|
||||
byte _objectFileNum;
|
||||
byte _idx;
|
||||
byte _flag1;
|
||||
byte _flag2;
|
||||
byte _flag3;
|
||||
byte _flag4;
|
||||
byte _flag5;
|
||||
byte _flag6;
|
||||
};
|
||||
|
||||
struct SpriteItem {
|
||||
int _animationType;
|
||||
const byte *_spriteData;
|
||||
Common::Point _spritePos;
|
||||
int _zoomFactor;
|
||||
bool _flipFl;
|
||||
int _spriteIndex;
|
||||
int _deltaX;
|
||||
int _deltaY;
|
||||
bool _rleFl;
|
||||
bool _activeFl;
|
||||
int _destX;
|
||||
int _destY;
|
||||
int _width;
|
||||
int _height;
|
||||
int _zoomPct;
|
||||
int _reducePct;
|
||||
};
|
||||
|
||||
struct BobItem {
|
||||
int _bobMode;
|
||||
byte *_spriteData;
|
||||
int _xp;
|
||||
int _yp;
|
||||
int _frameIndex;
|
||||
int _animDataIdx;
|
||||
int _moveChange1;
|
||||
int _moveChange2;
|
||||
bool _disabledAnimationFl;
|
||||
byte *_animData;
|
||||
bool _bobMode10;
|
||||
int _bobModeChange;
|
||||
int _modeChangeCtr;
|
||||
int _modeChangeUnused;
|
||||
bool _disableFl; // Set to true in B_CACHE_OFF()
|
||||
int _zoomFactor;
|
||||
bool _flipFl;
|
||||
bool _isSpriteFl;
|
||||
bool _activeFl;
|
||||
int _oldX;
|
||||
int _oldY;
|
||||
int _oldWidth;
|
||||
int _oldHeight;
|
||||
int _oldX2;
|
||||
int _zooInmFactor;
|
||||
int _zoomOutFactor;
|
||||
};
|
||||
|
||||
struct HidingItem {
|
||||
int _x;
|
||||
int _y;
|
||||
int _spriteIndex;
|
||||
int _width;
|
||||
int _height;
|
||||
int _useCount;
|
||||
byte *_spriteData;
|
||||
bool _resetUseCount;
|
||||
int _yOffset;
|
||||
};
|
||||
|
||||
struct LockAnimItem {
|
||||
bool _enableFl;
|
||||
int _posX;
|
||||
};
|
||||
|
||||
struct VBobItem {
|
||||
const byte *_spriteData;
|
||||
int _displayMode;
|
||||
int _xp;
|
||||
int _yp;
|
||||
int _frameIndex;
|
||||
byte *_surface;
|
||||
int _oldX;
|
||||
int _oldY;
|
||||
int _oldFrameIndex;
|
||||
const byte *_oldSpriteData;
|
||||
};
|
||||
|
||||
struct ListeItem {
|
||||
bool _visibleFl;
|
||||
int _posX;
|
||||
int _posY;
|
||||
int _width;
|
||||
int _height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mode for SortItem records
|
||||
*/
|
||||
enum SortMode { SORT_NONE = 0, SORT_BOB = 1, SORT_SPRITE = 2, SORT_HIDING = 3 };
|
||||
|
||||
/**
|
||||
* Structure to represent a pending display of either a Bob, Sprite, or Cache Item.
|
||||
*/
|
||||
struct SortItem {
|
||||
SortMode _sortMode;
|
||||
int _index;
|
||||
int _priority;
|
||||
};
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
class ObjectsManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
int _objectWidth, _objectHeight;
|
||||
int _oldBorderSpriteIndex;
|
||||
int _borderSpriteIndex;
|
||||
byte *_spritePtr;
|
||||
const byte *_oldSpriteData;
|
||||
int _verb;
|
||||
int _oldSpriteIndex;
|
||||
int _oldFrameIndex;
|
||||
int _oldDirectionSpriteIdx;
|
||||
Directions _oldDirection;
|
||||
Directions _lastDirection;
|
||||
bool _oldFlipFl;
|
||||
int _curGestureFile;
|
||||
byte *_gestureBuf;
|
||||
int _homeRateCounter;
|
||||
int _sortedDisplayCount;
|
||||
SortItem _sortedDisplay[51];
|
||||
byte *_hidingItemData[6];
|
||||
HidingItem _hidingItem[25];
|
||||
bool _hidingActiveFl;
|
||||
ObjectAuthIcon _objectAuthIcons[300];
|
||||
int _curObjectFileNum;
|
||||
byte *_objectDataBuf;
|
||||
|
||||
VBobItem _vBob[30];
|
||||
ListeItem _liste[6];
|
||||
ListeItem _liste2[35];
|
||||
|
||||
void initVBob();
|
||||
void clearVBob();
|
||||
|
||||
void sprite_alone(const byte *objectData, byte *sprite, int objIndex);
|
||||
void removeObjectDataBuf();
|
||||
|
||||
int getOffsetX(const byte *spriteData, int spriteIndex, bool isSize);
|
||||
int getOffsetY(const byte *spriteData, int spriteIndex, bool isSize);
|
||||
|
||||
void capture_mem_sprite(const byte *objectData, byte *sprite, int objIndex);
|
||||
void setBobInfo(int idx);
|
||||
void computeHideCounter(int idx);
|
||||
void initBobVariables(int idx);
|
||||
|
||||
void checkHidingItem();
|
||||
void displayHiding(int idx);
|
||||
void computeSprite(int idx);
|
||||
void beforeSort(SortMode sortMode, int index, int priority);
|
||||
void displayBobAnim();
|
||||
void displayVBob();
|
||||
void showSprite(int idx);
|
||||
void clearSprite();
|
||||
void setSpriteZoom(int idx, int zoomFactor);
|
||||
|
||||
void loadZone(const Common::Path &file);
|
||||
void changeCharacterHead(PlayerCharacter oldCharacter, PlayerCharacter newCharacter);
|
||||
void goHome2();
|
||||
|
||||
void nextVerbIcon();
|
||||
void handleForest(int screenId, int minX, int maxX, int minY, int maxY, int idx);
|
||||
|
||||
void sceneSpecialIni();
|
||||
void showActionAnimation(const byte *spriteData, const Common::String &actionStr, int speed, bool flipFl);
|
||||
public:
|
||||
bool _disableFl;
|
||||
bool _forestFl;
|
||||
bool _visibleFl;
|
||||
bool _saveLoadFl;
|
||||
bool _forceZoneFl;
|
||||
bool _changeVerbFl;
|
||||
bool _helicopterFl;
|
||||
bool _twoCharactersFl;
|
||||
bool _changeHeadFl;
|
||||
bool _priorityFl;
|
||||
int _jumpVerb;
|
||||
int _jumpZone;
|
||||
int _zoneNum;
|
||||
int _eraseVisibleCounter;
|
||||
int _curObjectIndex;
|
||||
int _startSpriteIndex;
|
||||
int _saveLoadX, _saveLoadY;
|
||||
int _mapCarPosX, _mapCarPosY;
|
||||
int _oldCharacterPosX, _oldCharacterPosY;
|
||||
Common::Point _borderPos;
|
||||
Common::Point _oldBorderPos;
|
||||
Common::Point _characterPos;
|
||||
byte *_forestSprite;
|
||||
byte *_saveLoadSprite;
|
||||
byte *_saveLoadSprite2;
|
||||
byte *_headSprites;
|
||||
SpriteItem _sprite[6];
|
||||
BobItem _bob[36];
|
||||
LockAnimItem _lockedAnims[36];
|
||||
bool _charactersEnabledFl;
|
||||
bool _refreshBobMode10Fl;
|
||||
|
||||
ObjectsManager(HopkinsEngine *vm);
|
||||
~ObjectsManager();
|
||||
|
||||
void clearAll();
|
||||
|
||||
int getWidth(const byte *objectData, int idx);
|
||||
int getHeight(const byte *objectData, int idx);
|
||||
byte *loadSprite(const Common::Path &file);
|
||||
void loadLinkFile(const Common::Path &file, bool OBSSEUL = false);
|
||||
void addStaticSprite(const byte *spriteData, Common::Point pos, int idx, int spriteIndex, int zoomFactor, bool flipFl, int deltaX, int deltaY);
|
||||
void animateSprite(int idx);
|
||||
void removeSprite(int idx);
|
||||
void setSpriteX(int idx, int xp);
|
||||
void setSpriteY(int idx, int yp);
|
||||
int getSpriteX(int idx);
|
||||
int getSpriteY(int idx);
|
||||
void setSpriteIndex(int idx, int spriteIndex);
|
||||
void displaySprite();
|
||||
void computeAndSetSpriteSize();
|
||||
void setFlipSprite(int idx, bool flip);
|
||||
|
||||
int getBobAnimDataIdx(int idx);
|
||||
void initBorder(int zoneIdx);
|
||||
void nextObjectIcon(int idx);
|
||||
void takeInventoryObject(int idx);
|
||||
void handleSpecialGames();
|
||||
|
||||
void addObject(int objIndex);
|
||||
void changeObject(int objIndex);
|
||||
void removeObject(int objIndex);
|
||||
|
||||
void resetBob(int idx);
|
||||
void hideBob(int idx);
|
||||
void displayBob(int idx);
|
||||
void setBobOffset(int idx, int offset);
|
||||
void setBobAnimDataIdx(int idx, int animIdx);
|
||||
void setBobAnimation(int idx);
|
||||
void stopBobAnimation(int idx);
|
||||
int getBobPosX(int idx);
|
||||
|
||||
void handleCityMap();
|
||||
void clearScreen();
|
||||
void disableVerb(int idx, int a2);
|
||||
void enableVerb(int idx, int a2);
|
||||
void lockAnimX(int idx, int x);
|
||||
void handleLeftButton();
|
||||
void handleRightButton();
|
||||
void setOffsetXY(byte *data, int idx, int xp, int yp, bool isSize);
|
||||
void setVerb(int id);
|
||||
|
||||
void doActionBack(int idx);
|
||||
void doActionRight(int idx);
|
||||
void doActionFront(int idx);
|
||||
void doActionLeft(int idx);
|
||||
void doActionDiagRight(int idx);
|
||||
void doActionDiagLeft(int idx);
|
||||
void loadObjects();
|
||||
byte *loadObjectFromFile(int objIndex, bool mode);
|
||||
void resetHidingItems();
|
||||
void resetHidingUseCount(int idx);
|
||||
void setHidingUseCount(int idx);
|
||||
void loadHidingItems(const Common::Path &file);
|
||||
void enableHidingBehavior();
|
||||
void disableHidingBehavior();
|
||||
void disableHidingItem(int idx);
|
||||
|
||||
void resetHomeRateCounter() { _homeRateCounter = 0; }
|
||||
void resetOldFrameIndex() { _oldFrameIndex = -1; }
|
||||
void resetOldDirection() { _oldDirection = DIR_NONE; }
|
||||
int getObjectWidth() { return _objectWidth; }
|
||||
int getObjectHeight() { return _objectHeight; }
|
||||
|
||||
void showSpecialActionAnimationWithFlip(const byte *spriteData, const Common::String &animationSeq, int speed, bool flipFl);
|
||||
void showSpecialActionAnimation(const byte *spriteData, const Common::String &animString, int speed);
|
||||
void checkEventBobAnim(int idx, int animIdx, int animDataIdx, int a4);
|
||||
void setMultiBobAnim(int idx1, int idx2, int anim1Idx, int anim2Idx);
|
||||
void loadObjectIniFile();
|
||||
void quickDisplayBobSprite(int idx);
|
||||
void initVbob(const byte *src, int idx, int xp, int yp, int frameIndex);
|
||||
void disableVbob(int idx);
|
||||
void setAndPlayAnim(int idx, int animIdx, int destPosi, bool animAction);
|
||||
|
||||
void sceneControl(const Common::Path &backgroundFile, const Common::Path &linkFile,
|
||||
const Common::Path &animFile, const Common::Path &s4, int soundNum, bool initializeScreen);
|
||||
void sceneControl2(const Common::Path &backgroundFile, const Common::Path &linkFile,
|
||||
const Common::Path &animFile, const Common::Path &s4, int soundNum, bool initializeScreen);
|
||||
void goHome();
|
||||
void paradise();
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_OBJECTS_H */
|
||||
339
engines/hopkins/saveload.cpp
Normal file
339
engines/hopkins/saveload.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
/* 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 "hopkins/saveload.h"
|
||||
|
||||
#include "hopkins/files.h"
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/scaler.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
const char *SAVEGAME_STR = "HOPKINS";
|
||||
#define SAVEGAME_STR_SIZE 13
|
||||
|
||||
SaveLoadManager::SaveLoadManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
}
|
||||
|
||||
bool SaveLoadManager::save(const Common::String &file, const void *buf, size_t n) {
|
||||
Common::OutSaveFile *savefile = g_system->getSavefileManager()->openForSaving(file);
|
||||
|
||||
if (savefile) {
|
||||
size_t bytesWritten = savefile->write(buf, n);
|
||||
savefile->finalize();
|
||||
delete savefile;
|
||||
|
||||
return bytesWritten == n;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SaveLoadManager::saveExists(const Common::String &file) {
|
||||
Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file);
|
||||
bool result = savefile != nullptr;
|
||||
delete savefile;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Save File
|
||||
bool SaveLoadManager::saveFile(const Common::String &file, const void *buf, size_t n) {
|
||||
return save(file, buf, n);
|
||||
}
|
||||
|
||||
void SaveLoadManager::load(const Common::String &file, byte *buf) {
|
||||
Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file);
|
||||
if (savefile == nullptr)
|
||||
error("Error opening file - %s", file.c_str());
|
||||
|
||||
int32 filesize = savefile->size();
|
||||
savefile->read(buf, filesize);
|
||||
delete savefile;
|
||||
}
|
||||
|
||||
WARN_UNUSED_RESULT bool SaveLoadManager::readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header, bool skipThumbnail) {
|
||||
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
|
||||
|
||||
// Validate the header Id
|
||||
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
|
||||
if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE))
|
||||
return false;
|
||||
|
||||
header._version = in->readByte();
|
||||
if (header._version > HOPKINS_SAVEGAME_VERSION)
|
||||
return false;
|
||||
|
||||
// Read in the string
|
||||
header._saveName.clear();
|
||||
char ch;
|
||||
while ((ch = (char)in->readByte()) != '\0') header._saveName += ch;
|
||||
|
||||
// Get the thumbnail
|
||||
if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read in save date/time
|
||||
header._year = in->readSint16LE();
|
||||
header._month = in->readSint16LE();
|
||||
header._day = in->readSint16LE();
|
||||
header._hour = in->readSint16LE();
|
||||
header._minute = in->readSint16LE();
|
||||
header._totalFrames = in->readUint32LE();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SaveLoadManager::writeSavegameHeader(Common::OutSaveFile *out, hopkinsSavegameHeader &header) {
|
||||
// Write out a savegame header
|
||||
out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
|
||||
|
||||
out->writeByte(HOPKINS_SAVEGAME_VERSION);
|
||||
|
||||
// Write savegame name
|
||||
out->write(header._saveName.c_str(), header._saveName.size() + 1);
|
||||
|
||||
// Create a thumbnail and save it
|
||||
Graphics::Surface *thumb = new Graphics::Surface();
|
||||
createThumbnail(thumb);
|
||||
Graphics::saveThumbnail(*out, *thumb);
|
||||
thumb->free();
|
||||
delete thumb;
|
||||
|
||||
// Write out the save date/time
|
||||
TimeDate td;
|
||||
g_system->getTimeAndDate(td);
|
||||
out->writeSint16LE(td.tm_year + 1900);
|
||||
out->writeSint16LE(td.tm_mon + 1);
|
||||
out->writeSint16LE(td.tm_mday);
|
||||
out->writeSint16LE(td.tm_hour);
|
||||
out->writeSint16LE(td.tm_min);
|
||||
out->writeUint32LE(_vm->_events->_gameCounter);
|
||||
}
|
||||
|
||||
Common::Error SaveLoadManager::saveGame(int slot, const Common::String &saveName) {
|
||||
/* Pack any necessary data into the savegame data structure */
|
||||
// Set the selected slot number
|
||||
_vm->_globals->_saveData->_data[svLastSavegameSlot] = slot;
|
||||
|
||||
// Set up the inventory
|
||||
for (int i = 0; i < 35; ++i)
|
||||
_vm->_globals->_saveData->_inventory[i] = _vm->_globals->_inventory[i];
|
||||
|
||||
_vm->_globals->_saveData->_mapCarPosX = _vm->_objectsMan->_mapCarPosX;
|
||||
_vm->_globals->_saveData->_mapCarPosY = _vm->_objectsMan->_mapCarPosY;
|
||||
|
||||
/* Create the savegame */
|
||||
Common::OutSaveFile *savefile = g_system->getSavefileManager()->openForSaving(
|
||||
_vm->getSaveStateName(slot));
|
||||
if (!savefile)
|
||||
return Common::kCreatingFileFailed;
|
||||
|
||||
// Set up the serializer
|
||||
Common::Serializer serializer(nullptr, savefile);
|
||||
|
||||
// Write out the savegame header
|
||||
hopkinsSavegameHeader header;
|
||||
header._saveName = saveName;
|
||||
header._version = HOPKINS_SAVEGAME_VERSION;
|
||||
writeSavegameHeader(savefile, header);
|
||||
|
||||
// Write out the savegame data
|
||||
syncSavegameData(serializer, header._version);
|
||||
|
||||
// Save file complete
|
||||
savefile->finalize();
|
||||
delete savefile;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error SaveLoadManager::loadGame(int slot) {
|
||||
// Try and open the save file for reading
|
||||
Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(
|
||||
_vm->getSaveStateName(slot));
|
||||
if (!savefile)
|
||||
return Common::kReadingFailed;
|
||||
|
||||
// Set up the serializer
|
||||
Common::Serializer serializer(savefile, nullptr);
|
||||
|
||||
// Read in the savegame header
|
||||
hopkinsSavegameHeader header;
|
||||
if (!readSavegameHeader(savefile, header)) {
|
||||
delete savefile;
|
||||
return Common::kReadingFailed;
|
||||
}
|
||||
|
||||
// Read in the savegame data
|
||||
syncSavegameData(serializer, header._version);
|
||||
|
||||
// Loading save file complete
|
||||
delete savefile;
|
||||
|
||||
// Unpack the inventory
|
||||
for (int i = 0; i < 35; ++i)
|
||||
_vm->_globals->_inventory[i] = _vm->_globals->_saveData->_inventory[i];
|
||||
|
||||
// Set variables from loaded data as necessary
|
||||
_vm->_globals->_saveData->_data[svLastSavegameSlot] = slot;
|
||||
_vm->_globals->_exitId = _vm->_globals->_saveData->_data[svLastScreenId];
|
||||
_vm->_globals->_saveData->_data[svLastPrevScreenId] = 0;
|
||||
_vm->_globals->_screenId = 0;
|
||||
_vm->_objectsMan->_mapCarPosX = _vm->_globals->_saveData->_mapCarPosX;
|
||||
_vm->_objectsMan->_mapCarPosY = _vm->_globals->_saveData->_mapCarPosY;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
WARN_UNUSED_RESULT bool SaveLoadManager::readSavegameHeader(int slot, hopkinsSavegameHeader &header, bool skipThumbnail) {
|
||||
// Try and open the save file for reading
|
||||
Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(
|
||||
_vm->getSaveStateName(slot));
|
||||
if (!savefile)
|
||||
return false;
|
||||
|
||||
bool result = readSavegameHeader(savefile, header, skipThumbnail);
|
||||
delete savefile;
|
||||
return result;
|
||||
}
|
||||
|
||||
#define REDUCE_AMOUNT 80
|
||||
|
||||
void SaveLoadManager::createThumbnail(Graphics::Surface *s) {
|
||||
int w = _vm->_graphicsMan->zoomOut(SCREEN_WIDTH, REDUCE_AMOUNT);
|
||||
int h = _vm->_graphicsMan->zoomOut(SCREEN_HEIGHT - 40, REDUCE_AMOUNT);
|
||||
|
||||
Graphics::Surface thumb8;
|
||||
thumb8.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
_vm->_graphicsMan->reduceScreenPart(_vm->_graphicsMan->_frontBuffer, (byte *)thumb8.getPixels(),
|
||||
_vm->_events->_startPos.x, 20, SCREEN_WIDTH, SCREEN_HEIGHT - 40, 80);
|
||||
|
||||
// Convert the 8-bit pixel to 16 bit surface
|
||||
s->create(w, h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
|
||||
|
||||
const byte *srcP = (const byte *)thumb8.getPixels();
|
||||
uint16 *destP = (uint16 *)s->getPixels();
|
||||
|
||||
for (int yp = 0; yp < h; ++yp) {
|
||||
// Copy over the line, using the source pixels as lookups into the pixels palette
|
||||
const byte *lineSrcP = srcP;
|
||||
uint16 *lineDestP = destP;
|
||||
|
||||
for (int xp = 0; xp < w; ++xp)
|
||||
*lineDestP++ = *(uint16 *)&_vm->_graphicsMan->_palettePixels[*lineSrcP++ * 2];
|
||||
|
||||
// Move to the start of the next line
|
||||
srcP += w;
|
||||
destP += w;
|
||||
}
|
||||
thumb8.free();
|
||||
}
|
||||
|
||||
void SaveLoadManager::syncSavegameData(Common::Serializer &s, int version) {
|
||||
// The brief version 3 had the highscores embedded. They're in a separate file now, so skip
|
||||
if (version == 3 && s.isLoading())
|
||||
s.skip(100);
|
||||
|
||||
s.syncBytes(&_vm->_globals->_saveData->_data[0], 2050);
|
||||
syncCharacterLocation(s, _vm->_globals->_saveData->_cloneHopkins);
|
||||
syncCharacterLocation(s, _vm->_globals->_saveData->_realHopkins);
|
||||
syncCharacterLocation(s, _vm->_globals->_saveData->_samantha);
|
||||
|
||||
for (int i = 0; i < 35; ++i)
|
||||
s.syncAsSint16LE(_vm->_globals->_saveData->_inventory[i]);
|
||||
|
||||
if (version > 1) {
|
||||
s.syncAsSint16LE(_vm->_globals->_saveData->_mapCarPosX);
|
||||
s.syncAsSint16LE(_vm->_globals->_saveData->_mapCarPosY);
|
||||
} else {
|
||||
_vm->_globals->_saveData->_mapCarPosX = _vm->_globals->_saveData->_mapCarPosY = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SaveLoadManager::syncCharacterLocation(Common::Serializer &s, CharacterLocation &item) {
|
||||
s.syncAsSint16LE(item._pos.x);
|
||||
s.syncAsSint16LE(item._pos.y);
|
||||
s.syncAsSint16LE(item._startSpriteIndex);
|
||||
s.syncAsSint16LE(item._location);
|
||||
s.syncAsSint16LE(item._zoomFactor);
|
||||
}
|
||||
|
||||
void SaveLoadManager::convertThumb16To8(Graphics::Surface *thumb16, Graphics::Surface *thumb8) {
|
||||
thumb8->create(thumb16->w, thumb16->h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
Graphics::PixelFormat pixelFormat16(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
||||
|
||||
byte paletteR[PALETTE_SIZE];
|
||||
byte paletteG[PALETTE_SIZE];
|
||||
byte paletteB[PALETTE_SIZE];
|
||||
for (int palIndex = 0; palIndex < PALETTE_SIZE; ++palIndex) {
|
||||
uint16 p = READ_UINT16(&_vm->_graphicsMan->_palettePixels[palIndex * 2]);
|
||||
pixelFormat16.colorToRGB(p, paletteR[palIndex], paletteG[palIndex], paletteB[palIndex]);
|
||||
}
|
||||
|
||||
const uint16 *srcP = (const uint16 *)thumb16->getPixels();
|
||||
byte *destP = (byte *)thumb8->getPixels();
|
||||
|
||||
for (int yp = 0; yp < thumb16->h; ++yp) {
|
||||
const uint16 *lineSrcP = srcP;
|
||||
byte *lineDestP = destP;
|
||||
|
||||
for (int xp = 0; xp < thumb16->w; ++xp) {
|
||||
byte r, g, b;
|
||||
pixelFormat16.colorToRGB(*lineSrcP++, r, g, b);
|
||||
|
||||
// Do like in the original and show thumbnail as a grayscale picture
|
||||
int lum = (r * 21 + g * 72 + b * 7) / 100;
|
||||
r = g = b = lum;
|
||||
|
||||
// Scan the palette for the closest match
|
||||
int difference = 99999, foundIndex = 0;
|
||||
for (int palIndex = 0; palIndex < PALETTE_SIZE; ++palIndex) {
|
||||
byte rCurrent = paletteR[palIndex];
|
||||
byte gCurrent = paletteG[palIndex];
|
||||
byte bCurrent = paletteB[palIndex];
|
||||
|
||||
int diff = ABS((int)r - (int)rCurrent) + ABS((int)g - (int)gCurrent) + ABS((int)b - (int)bCurrent);
|
||||
if (diff < difference) {
|
||||
difference = diff;
|
||||
foundIndex = palIndex;
|
||||
}
|
||||
}
|
||||
|
||||
*lineDestP++ = foundIndex;
|
||||
}
|
||||
|
||||
// Move to the start of the next line
|
||||
srcP += thumb16->w;
|
||||
destP += thumb16->w;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Hopkins
|
||||
77
engines/hopkins/saveload.h
Normal file
77
engines/hopkins/saveload.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 HOPKINS_SAVELOAD_H
|
||||
#define HOPKINS_SAVELOAD_H
|
||||
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/graphics.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
#define HOPKINS_SAVEGAME_VERSION 4
|
||||
|
||||
struct hopkinsSavegameHeader {
|
||||
uint8 _version;
|
||||
Common::String _saveName;
|
||||
Graphics::Surface *_thumbnail;
|
||||
int _year, _month, _day;
|
||||
int _hour, _minute;
|
||||
int _totalFrames;
|
||||
};
|
||||
|
||||
class SaveLoadManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
void createThumbnail(Graphics::Surface *s);
|
||||
void syncSavegameData(Common::Serializer &s, int version);
|
||||
void syncCharacterLocation(Common::Serializer &s, CharacterLocation &item);
|
||||
public:
|
||||
SaveLoadManager(HopkinsEngine *vm);
|
||||
|
||||
bool saveExists(const Common::String &file);
|
||||
bool save(const Common::String &file, const void *buf, size_t n);
|
||||
bool saveFile(const Common::String &file, const void *buf, size_t n);
|
||||
void load(const Common::String &file, byte *buf);
|
||||
|
||||
WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header, bool skipThumbnail = true);
|
||||
void writeSavegameHeader(Common::OutSaveFile *out, hopkinsSavegameHeader &header);
|
||||
WARN_UNUSED_RESULT bool readSavegameHeader(int slot, hopkinsSavegameHeader &header, bool skipThumbnail = true);
|
||||
Common::Error saveGame(int slot, const Common::String &saveName);
|
||||
Common::Error loadGame(int slot);
|
||||
|
||||
/**
|
||||
* Converts a 16-bit thumbnail to 8 bit paletted using the currently active palette.
|
||||
*/
|
||||
void convertThumb16To8(Graphics::Surface *thumb16, Graphics::Surface *thumb8);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_SAVELOAD_H */
|
||||
2686
engines/hopkins/script.cpp
Normal file
2686
engines/hopkins/script.cpp
Normal file
File diff suppressed because it is too large
Load Diff
49
engines/hopkins/script.h
Normal file
49
engines/hopkins/script.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HOPKINS_SCRIPT_H
|
||||
#define HOPKINS_SCRIPT_H
|
||||
|
||||
#include "hopkins/globals.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class ScriptManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
int checkOpcode(const byte *dataP);
|
||||
public:
|
||||
bool _tempObjectFl;
|
||||
|
||||
ScriptManager(HopkinsEngine *vm);
|
||||
|
||||
int handleOpcode(const byte *dataP);
|
||||
int handleIf(const byte *dataP, int offset);
|
||||
int handleGoto(const byte *dataP);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_SCRIPT_H */
|
||||
949
engines/hopkins/sound.cpp
Normal file
949
engines/hopkins/sound.cpp
Normal file
@@ -0,0 +1,949 @@
|
||||
/* 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 "hopkins/sound.h"
|
||||
|
||||
#include "hopkins/globals.h"
|
||||
#include "hopkins/hopkins.h"
|
||||
|
||||
#include "audio/decoders/adpcm_intern.h"
|
||||
#include "audio/decoders/wave.h"
|
||||
#include "audio/softsynth/pcspk.h"
|
||||
#include "common/system.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/mods/module.h"
|
||||
#include "audio/mods/protracker.h"
|
||||
#include "audio/decoders/raw.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class APC_ADPCMStream : public Audio::DVI_ADPCMStream {
|
||||
public:
|
||||
APC_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, int rate, int channels) : DVI_ADPCMStream(stream, disposeAfterUse, stream->size(), rate, channels, 0) {
|
||||
stream->seek(-12, SEEK_CUR);
|
||||
_status.ima_ch[0].last = _startValue[0] = stream->readUint32LE();
|
||||
_status.ima_ch[1].last = _startValue[1] = stream->readUint32LE();
|
||||
stream->seek(4, SEEK_CUR);
|
||||
}
|
||||
|
||||
void reset() override {
|
||||
DVI_ADPCMStream::reset();
|
||||
_status.ima_ch[0].last = _startValue[0];
|
||||
_status.ima_ch[1].last = _startValue[1];
|
||||
}
|
||||
|
||||
private:
|
||||
int16 _startValue[2];
|
||||
};
|
||||
|
||||
Audio::RewindableAudioStream *makeAPCStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
|
||||
if (stream->readUint32BE() != MKTAG('C', 'R', 'Y', 'O'))
|
||||
return nullptr;
|
||||
if (stream->readUint32BE() != MKTAG('_', 'A', 'P', 'C'))
|
||||
return nullptr;
|
||||
stream->readUint32BE(); // version
|
||||
stream->readUint32LE(); // out size
|
||||
uint32 rate = stream->readUint32LE();
|
||||
stream->skip(8); // initial values, will be handled by the class
|
||||
bool stereo = stream->readUint32LE() != 0;
|
||||
|
||||
return new APC_ADPCMStream(stream, disposeAfterUse, rate, stereo ? 2 : 1);
|
||||
}
|
||||
|
||||
class TwaAudioStream : public Audio::AudioStream {
|
||||
public:
|
||||
TwaAudioStream(const Common::Path &name, Common::SeekableReadStream *stream) {
|
||||
_name = name;
|
||||
_cueSheet.clear();
|
||||
_cueStream = nullptr;
|
||||
_cue = 0;
|
||||
_loadedCue = -1;
|
||||
|
||||
for (;;) {
|
||||
char buf[3];
|
||||
stream->read(buf, 3);
|
||||
|
||||
if (buf[0] == 'x' || stream->eos())
|
||||
break;
|
||||
|
||||
_cueSheet.push_back(atol(buf));
|
||||
}
|
||||
|
||||
for (_cue = 0; _cue < _cueSheet.size(); _cue++) {
|
||||
if (loadCue(_cue))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~TwaAudioStream() override {
|
||||
delete _cueStream;
|
||||
_cueStream = nullptr;
|
||||
}
|
||||
|
||||
bool isStereo() const override {
|
||||
return _cueStream ? _cueStream->isStereo() : true;
|
||||
}
|
||||
|
||||
int getRate() const override {
|
||||
return _cueStream ? _cueStream->getRate() : 22050;
|
||||
}
|
||||
|
||||
bool endOfData() const override {
|
||||
return _cueStream == nullptr;
|
||||
}
|
||||
|
||||
int readBuffer(int16 *buffer, const int numSamples) override {
|
||||
if (!_cueStream)
|
||||
return 0;
|
||||
|
||||
int16 *buf = buffer;
|
||||
int samplesLeft = numSamples;
|
||||
|
||||
while (samplesLeft) {
|
||||
if (_cueStream) {
|
||||
int readSamples = _cueStream->readBuffer(buf, samplesLeft);
|
||||
buf += readSamples;
|
||||
samplesLeft -= readSamples;
|
||||
}
|
||||
|
||||
if (samplesLeft > 0) {
|
||||
if (++_cue >= _cueSheet.size()) {
|
||||
_cue = 0;
|
||||
}
|
||||
loadCue(_cue);
|
||||
}
|
||||
}
|
||||
|
||||
return numSamples;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool loadCue(int nr) {
|
||||
if (_loadedCue == _cueSheet[nr]) {
|
||||
_cueStream->rewind();
|
||||
return true;
|
||||
}
|
||||
|
||||
delete _cueStream;
|
||||
_cueStream = nullptr;
|
||||
_loadedCue = _cueSheet[nr];
|
||||
|
||||
Common::Path filename(_name);
|
||||
filename.appendInPlace(Common::String::format("_%02d", _cueSheet[nr]));
|
||||
|
||||
Common::File *file = new Common::File();
|
||||
|
||||
if (file->open(filename.append(".APC"))) {
|
||||
_cueStream = makeAPCStream(file, DisposeAfterUse::YES);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (file->open(filename.append(".WAV"))) {
|
||||
_cueStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (file->open(filename.append(".RAW"))) {
|
||||
_cueStream = Audio::makeRawStream(file, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
|
||||
return true;
|
||||
}
|
||||
|
||||
warning("TwaAudioStream::loadCue: Missing cue %d (%s)", nr, filename.toString().c_str());
|
||||
_loadedCue = -1;
|
||||
delete file;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Common::Path _name;
|
||||
Common::Array<int> _cueSheet;
|
||||
Audio::RewindableAudioStream *_cueStream;
|
||||
uint _cue;
|
||||
int _loadedCue;
|
||||
};
|
||||
|
||||
Audio::AudioStream *makeTwaStream(const Common::Path &name, Common::SeekableReadStream *stream) {
|
||||
return new TwaAudioStream(name, stream);
|
||||
}
|
||||
|
||||
SoundManager::SoundManager(HopkinsEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
_specialSoundNum = 0;
|
||||
_soundVolume = 0;
|
||||
_voiceVolume = 0;
|
||||
_musicVolume = 0;
|
||||
_soundOffFl = true;
|
||||
_musicOffFl = true;
|
||||
_voiceOffFl = true;
|
||||
_textOffFl = false;
|
||||
_soundFl = false;
|
||||
_skipRefreshFl = false;
|
||||
_currentSoundIndex = 0;
|
||||
_oldSoundNumber = 0;
|
||||
_modPlayingFl = false;
|
||||
}
|
||||
|
||||
SoundManager::~SoundManager() {
|
||||
stopMusic();
|
||||
delMusic();
|
||||
_vm->_mixer->stopHandle(_musicHandle);
|
||||
_modPlayingFl = false;
|
||||
}
|
||||
|
||||
void SoundManager::checkSoundEnd() {
|
||||
if (!_soundOffFl && _soundFl) {
|
||||
if (!checkVoiceStatus(1)) {
|
||||
stopVoice(1);
|
||||
delWav(_currentSoundIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::loadAnimSound() {
|
||||
switch (_specialSoundNum) {
|
||||
case 2:
|
||||
loadSample(5, "mitra1.wav");
|
||||
loadSample(1, "tir2.wav");
|
||||
loadSample(2, "sound6.wav");
|
||||
loadSample(3, "sound5.WAV");
|
||||
loadSample(4, "sound4.WAV");
|
||||
break;
|
||||
case 5:
|
||||
loadWav("CRIE.WAV", 1);
|
||||
break;
|
||||
case 14:
|
||||
loadWav("SOUND14.WAV", 1);
|
||||
break;
|
||||
case 16:
|
||||
loadWav("SOUND16.WAV", 1);
|
||||
break;
|
||||
case 198:
|
||||
loadWav("SOUND3.WAV", 1);
|
||||
break;
|
||||
case 199:
|
||||
loadWav("SOUND22.WAV", 1);
|
||||
break;
|
||||
case 200:
|
||||
mixVoice(682, 1);
|
||||
break;
|
||||
case 208:
|
||||
loadWav("SOUND77.WAV", 1);
|
||||
break;
|
||||
case 210:
|
||||
loadWav("SOUND78.WAV", 1);
|
||||
break;
|
||||
case 211:
|
||||
loadWav("SOUND78.WAV", 1);
|
||||
break;
|
||||
case 229:
|
||||
loadWav("SOUND80.WAV", 1);
|
||||
loadWav("SOUND82.WAV", 2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::playAnimSound(int animFrame) {
|
||||
if (!_vm->_globals->_censorshipFl && _specialSoundNum == 2) {
|
||||
switch (animFrame) {
|
||||
case 20:
|
||||
playSample(5);
|
||||
break;
|
||||
case 57:
|
||||
case 63:
|
||||
case 69:
|
||||
playSample(1);
|
||||
break;
|
||||
case 75:
|
||||
// This removes the sound of the gun played while the guard is being shot, as this part of the scene has been
|
||||
// removed in the Polish version of the game
|
||||
if (_vm->getLanguage() != Common::PL_POL)
|
||||
playSample(2);
|
||||
break;
|
||||
case 95:
|
||||
// This fixes an original bug in the Polish version of the game, which was literally butchered for some reason
|
||||
if (_vm->getLanguage() == Common::PL_POL)
|
||||
playSample(3);
|
||||
break;
|
||||
case 109:
|
||||
if (_vm->getLanguage() != Common::PL_POL)
|
||||
playSample(3);
|
||||
break;
|
||||
case 108:
|
||||
// This fixes an original bug in the Polish version of the game, which was literally butchered for some reason
|
||||
if (_vm->getLanguage() == Common::PL_POL)
|
||||
playSample(4);
|
||||
break;
|
||||
case 122:
|
||||
if (_vm->getLanguage() != Common::PL_POL)
|
||||
playSample(4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (_specialSoundNum == 1 && animFrame == 17)
|
||||
playSoundFile("SOUND42.WAV");
|
||||
else if (_specialSoundNum == 5 && animFrame == 19)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 14 && animFrame == 625)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 16 && animFrame == 25)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 17) {
|
||||
if (animFrame == 6)
|
||||
playSample(1);
|
||||
else if (animFrame == 14)
|
||||
playSample(2);
|
||||
else if (animFrame == 67)
|
||||
playSample(3);
|
||||
} else if (_specialSoundNum == 198 && animFrame == 15)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 199 && animFrame == 72)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 208 && animFrame == 40)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 210 && animFrame == 2)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 211 && animFrame == 22)
|
||||
playWav(1);
|
||||
else if (_specialSoundNum == 229) {
|
||||
if (animFrame == 15)
|
||||
playWav(1);
|
||||
else if (animFrame == 91)
|
||||
playWav(2);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *const modSounds[] = {
|
||||
"appart", "ville", "Rock", "police", "deep",
|
||||
"purgat", "riviere", "SUSPENS", "labo", "cadavre",
|
||||
"cabane", "purgat2", "foret", "ile", "ile2",
|
||||
"hopkins", "peur", "URAVOLGA", "BASE", "cadavre2",
|
||||
"usine", "chien", "coeur", "stand", "ocean",
|
||||
"base3", "gloop", "cant", "feel", "lost",
|
||||
"tobac"
|
||||
};
|
||||
|
||||
void SoundManager::playSound(int soundNumber) {
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
|
||||
if (soundNumber > 27)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_oldSoundNumber != soundNumber || !_modPlayingFl) {
|
||||
if (_modPlayingFl)
|
||||
stopSound();
|
||||
|
||||
playMod(modSounds[soundNumber - 1]);
|
||||
_oldSoundNumber = soundNumber;
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::stopSound() {
|
||||
stopVoice(0);
|
||||
stopVoice(1);
|
||||
stopVoice(2);
|
||||
if (_soundFl)
|
||||
delWav(_currentSoundIndex);
|
||||
|
||||
for (int i = 1; i <= 48; ++i)
|
||||
removeWavSample(i);
|
||||
|
||||
if (_modPlayingFl) {
|
||||
stopMusic();
|
||||
delMusic();
|
||||
_modPlayingFl = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::playMod(const Common::Path &file) {
|
||||
if (_musicOffFl)
|
||||
return;
|
||||
Common::String modFile = file.baseName();
|
||||
|
||||
// HACK
|
||||
if (modFile == "URAVOLGA" && (_vm->getPlatform() == Common::kPlatformWindows || _vm->getPlatform() == Common::kPlatformLinux))
|
||||
modFile = "peur";
|
||||
|
||||
// The Windows/Linux version chops off the music file names to 5 characters
|
||||
if (modFile.size() > 5 && (_vm->getPlatform() == Common::kPlatformWindows || _vm->getPlatform() == Common::kPlatformLinux)) {
|
||||
if (!modFile.hasSuffix("2")) {
|
||||
while (modFile.size() > 5)
|
||||
modFile.deleteLastChar();
|
||||
} else {
|
||||
while (modFile.size() > 4)
|
||||
modFile.deleteLastChar();
|
||||
modFile += "2";
|
||||
}
|
||||
}
|
||||
if (_modPlayingFl) {
|
||||
stopMusic();
|
||||
delMusic();
|
||||
_modPlayingFl = false;
|
||||
}
|
||||
|
||||
loadMusic(file.getParent().appendComponent(modFile));
|
||||
playMusic();
|
||||
_modPlayingFl = true;
|
||||
}
|
||||
|
||||
void SoundManager::loadMusic(const Common::Path &file) {
|
||||
if (_music._active)
|
||||
delMusic();
|
||||
|
||||
Common::File f;
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
|
||||
Common::Path filename(file);
|
||||
filename.appendInPlace(".MOD");
|
||||
|
||||
if (!f.open(filename))
|
||||
error("Error opening file %s", filename.toString().c_str());
|
||||
|
||||
Modules::Module *module;
|
||||
Audio::AudioStream *modStream = Audio::makeProtrackerStream(&f, 0, 44100, true, &module);
|
||||
|
||||
// WORKAROUND: This song is played at the empty lot where the
|
||||
// bank robbers have left the helicopter. The MOD file appears
|
||||
// to be slightly broken. Almost half of it is just the same
|
||||
// noise repeating. We fix this by only playing the working
|
||||
// part of it. The result is pretty close to the Windows music.
|
||||
if (file.equalsIgnoreCase("cadavre")) {
|
||||
module->songlen = 3;
|
||||
}
|
||||
|
||||
_vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, modStream);
|
||||
|
||||
} else {
|
||||
Common::Path filename(file);
|
||||
filename.appendInPlace(".TWA");
|
||||
|
||||
if (!f.open(filename))
|
||||
error("Error opening file %s", filename.toString().c_str());
|
||||
|
||||
Audio::AudioStream *twaStream = makeTwaStream(file, &f);
|
||||
_vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, twaStream);
|
||||
f.close();
|
||||
}
|
||||
|
||||
_music._active = true;
|
||||
}
|
||||
|
||||
void SoundManager::playMusic() {
|
||||
}
|
||||
|
||||
void SoundManager::stopMusic() {
|
||||
_vm->_mixer->stopHandle(_musicHandle);
|
||||
}
|
||||
|
||||
void SoundManager::delMusic() {
|
||||
_music._active = false;
|
||||
}
|
||||
|
||||
void SoundManager::checkSounds() {
|
||||
checkVoiceActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks voices to see if they're finished
|
||||
*/
|
||||
void SoundManager::checkVoiceActivity() {
|
||||
// Check the status of each voice.
|
||||
bool hasActiveVoice = false;
|
||||
for (int i = 0; i < VOICE_COUNT; ++i)
|
||||
hasActiveVoice |= checkVoiceStatus(i);
|
||||
|
||||
if (!hasActiveVoice && _soundFl) {
|
||||
_soundFl = false;
|
||||
_currentSoundIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
|
||||
int fileNumber;
|
||||
bool breakFlag;
|
||||
Common::String prefix;
|
||||
Common::Path filename;
|
||||
Common::File f;
|
||||
size_t catPos, catLen;
|
||||
|
||||
fileNumber = voiceId;
|
||||
if (_voiceOffFl)
|
||||
return false;
|
||||
|
||||
if ((voiceMode == 1 || voiceMode == 2)
|
||||
&& ( voiceId == 4 || voiceId == 16 || voiceId == 121
|
||||
|| voiceId == 142 || voiceId == 182 || voiceId == 191
|
||||
|| voiceId == 212 || voiceId == 225 || voiceId == 239
|
||||
|| voiceId == 245 || voiceId == 297 || voiceId == 308
|
||||
|| voiceId == 333 || voiceId == 348 || voiceId == 352
|
||||
|| voiceId == 358 || voiceId == 364 || voiceId == 371
|
||||
|| voiceId == 394 || voiceId == 414 || voiceId == 429
|
||||
|| voiceId == 442 || voiceId == 446 || voiceId == 461
|
||||
|| voiceId == 468 || voiceId == 476 || voiceId == 484
|
||||
|| voiceId == 491 || voiceId == 497 || voiceId == 501
|
||||
|| voiceId == 511 || voiceId == 520 || voiceId == 536
|
||||
|| voiceId == 554 || voiceId == 566 || voiceId == 573
|
||||
|| voiceId == 632 || voiceId == 645))
|
||||
fileNumber = 684;
|
||||
|
||||
if (voiceMode == 1 || voiceMode == 2)
|
||||
prefix = "DF";
|
||||
else if (voiceMode == 3)
|
||||
prefix = "IF";
|
||||
else if (voiceMode == 4)
|
||||
prefix = "TF";
|
||||
else if (voiceMode == 5)
|
||||
prefix = "OF";
|
||||
|
||||
// BeOS and OS/2 versions are using a slightly different speech order during intro
|
||||
// This map those values to the ones used by the Win95 and Linux versions
|
||||
int mappedFileNumber = fileNumber;
|
||||
if (voiceMode == 3 && (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)) {
|
||||
if (fileNumber == 4)
|
||||
mappedFileNumber = 0;
|
||||
else if (fileNumber > 4)
|
||||
mappedFileNumber = fileNumber - 1;
|
||||
}
|
||||
|
||||
filename = Common::Path(Common::String::format("%s%d", prefix.c_str(), mappedFileNumber));
|
||||
|
||||
bool fileFoundFl = false;
|
||||
_vm->_fileIO->searchCat(filename.append(".WAV"), RES_VOI, fileFoundFl);
|
||||
if (fileFoundFl) {
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
|
||||
filename = "ENG_VOI.RES";
|
||||
} else {
|
||||
// Win95 and Linux versions uses another set of names
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_FR:
|
||||
filename = "RES_VFR.RES";
|
||||
break;
|
||||
case LANG_EN:
|
||||
filename = "RES_VAN.RES";
|
||||
break;
|
||||
case LANG_SP:
|
||||
filename = "RES_VES.RES";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
catPos = _vm->_fileIO->_catalogPos;
|
||||
catLen = _vm->_fileIO->_catalogSize;
|
||||
} else {
|
||||
_vm->_fileIO->searchCat(filename.append(".APC"), RES_VOI, fileFoundFl);
|
||||
if (fileFoundFl) {
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
|
||||
filename = "ENG_VOI.RES";
|
||||
} else {
|
||||
// Win95 and Linux versions uses another set of names
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_FR:
|
||||
filename = "RES_VFR.RES";
|
||||
break;
|
||||
case LANG_EN:
|
||||
filename = "RES_VAN.RES";
|
||||
break;
|
||||
case LANG_SP:
|
||||
filename = "RES_VES.RES";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
catPos = _vm->_fileIO->_catalogPos;
|
||||
catLen = _vm->_fileIO->_catalogSize;
|
||||
} else {
|
||||
_vm->_fileIO->searchCat(filename.append(".RAW"), RES_VOI, fileFoundFl);
|
||||
if (fileFoundFl) {
|
||||
if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
|
||||
filename = "ENG_VOI.RES";
|
||||
} else {
|
||||
// Win95 and Linux versions uses another set of names
|
||||
switch (_vm->_globals->_language) {
|
||||
case LANG_FR:
|
||||
filename = "RES_VFR.RES";
|
||||
break;
|
||||
case LANG_EN:
|
||||
filename = "RES_VAN.RES";
|
||||
break;
|
||||
case LANG_SP:
|
||||
filename = "RES_VES.RES";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
catPos = _vm->_fileIO->_catalogPos;
|
||||
catLen = _vm->_fileIO->_catalogSize;
|
||||
} else {
|
||||
if (!f.exists(filename.append(".WAV"))) {
|
||||
if (!f.exists(filename.append(".APC")))
|
||||
return false;
|
||||
filename.appendInPlace(".APC");
|
||||
} else
|
||||
filename.appendInPlace(".WAV");
|
||||
|
||||
catPos = 0;
|
||||
catLen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
int oldMusicVol = _musicVolume;
|
||||
if (!loadVoice(filename, catPos, catLen, _sWav[20])) {
|
||||
// This case only concerns the English Win95 demo
|
||||
// If it's not possible to load the voice, we force the active flag
|
||||
// to false in order to make sure the missing buffer won't be played
|
||||
// accidentally later
|
||||
_sWav[20]._active = false;
|
||||
} else {
|
||||
_sWav[20]._active = true;
|
||||
|
||||
// Reduce music volume during speech
|
||||
if (!_musicOffFl && _musicVolume > 2) {
|
||||
_musicVolume -= _musicVolume * 9 / 20;
|
||||
setMODMusicVolume(_musicVolume);
|
||||
}
|
||||
}
|
||||
playVoice();
|
||||
|
||||
_vm->_events->_escKeyFl = false;
|
||||
|
||||
// Loop for playing voice
|
||||
breakFlag = false;
|
||||
do {
|
||||
if (_specialSoundNum != 4 && !_skipRefreshFl)
|
||||
_vm->_events->refreshScreenAndEvents();
|
||||
if (_vm->_events->getMouseButton())
|
||||
break;
|
||||
_vm->_events->refreshEvents();
|
||||
if (_vm->_events->_escKeyFl)
|
||||
break;
|
||||
// We only check the voice status if the file has been loaded properly
|
||||
// This avoids skipping completely the talk animations in the Win95 UK Demo
|
||||
if (!checkVoiceStatus(2) && _sWav[20]._active)
|
||||
breakFlag = true;
|
||||
// This is specific to the Win95 UK Demo again: if nothing is displayed,
|
||||
// don't wait for a click event.
|
||||
if (!_sWav[20]._active && !dispTxtFl)
|
||||
break;
|
||||
} while (!_vm->shouldQuit() && !breakFlag);
|
||||
|
||||
|
||||
stopVoice(2);
|
||||
removeWavSample(20);
|
||||
|
||||
// Speech is over, set the music volume back to normal
|
||||
_musicVolume = oldMusicVol;
|
||||
if (!_musicOffFl && _musicVolume > 2) {
|
||||
setMODMusicVolume(_musicVolume);
|
||||
}
|
||||
_vm->_events->_escKeyFl = false;
|
||||
_skipRefreshFl = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SoundManager::removeSample(int soundIndex) {
|
||||
if (checkVoiceStatus(1))
|
||||
stopVoice(1);
|
||||
if (checkVoiceStatus(2))
|
||||
stopVoice(2);
|
||||
removeWavSample(soundIndex);
|
||||
_sound[soundIndex]._active = false;
|
||||
}
|
||||
|
||||
void SoundManager::playSoundFile(const Common::Path &file) {
|
||||
if (_soundOffFl)
|
||||
return;
|
||||
|
||||
// Fallback for the menu option.
|
||||
// The BeOS and OS/2 versions don't play sound at this point.
|
||||
// sound20 sounds very close to bruit2 from the linux and Win95 versions.
|
||||
Common::File f;
|
||||
Common::Path filename;
|
||||
if (file == "bruit2.wav" && !f.exists(file))
|
||||
filename = "sound20.wav";
|
||||
else
|
||||
filename = file;
|
||||
|
||||
if (_soundFl)
|
||||
delWav(_currentSoundIndex);
|
||||
loadWav(filename, 1);
|
||||
playWav(1);
|
||||
}
|
||||
|
||||
void SoundManager::directPlayWav(const Common::Path &file) {
|
||||
if (_soundOffFl)
|
||||
return;
|
||||
|
||||
loadWav(file, 1);
|
||||
playWav(1);
|
||||
}
|
||||
|
||||
void SoundManager::setMODSampleVolume() {
|
||||
for (int idx = 0; idx < SWAV_COUNT; ++idx) {
|
||||
if (idx != 20 && _sWav[idx]._active) {
|
||||
int volume = _soundVolume * 255 / 16;
|
||||
_vm->_mixer->setChannelVolume(_sWav[idx]._soundHandle, volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::setMODVoiceVolume() {
|
||||
if (_sWav[20]._active) {
|
||||
int volume = _voiceVolume * 255 / 16;
|
||||
_vm->_mixer->setChannelVolume(_sWav[20]._soundHandle, volume);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::setMODMusicVolume(int volume) {
|
||||
if (_vm->_mixer->isSoundHandleActive(_musicHandle))
|
||||
_vm->_mixer->setChannelVolume(_musicHandle, volume * 255 / 16);
|
||||
}
|
||||
|
||||
void SoundManager::loadSample(int wavIndex, const Common::Path &file) {
|
||||
loadWavSample(wavIndex, file, false);
|
||||
_sound[wavIndex]._active = true;
|
||||
}
|
||||
|
||||
void SoundManager::playSample(int wavIndex, int voiceMode) {
|
||||
if (_soundOffFl || !_sound[wavIndex]._active)
|
||||
return;
|
||||
|
||||
if (_soundFl)
|
||||
delWav(_currentSoundIndex);
|
||||
|
||||
switch (voiceMode) {
|
||||
case 5:
|
||||
// Case added to identify the former PLAY_SAMPLE2 calls
|
||||
case 9:
|
||||
if (checkVoiceStatus(1))
|
||||
stopVoice(1);
|
||||
playWavSample(1, wavIndex);
|
||||
break;
|
||||
case 6:
|
||||
if (checkVoiceStatus(2))
|
||||
stopVoice(1);
|
||||
playWavSample(2, wavIndex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundManager::checkVoiceStatus(int voiceIndex) {
|
||||
if (_voice[voiceIndex]._status) {
|
||||
int wavIndex = _voice[voiceIndex]._wavIndex;
|
||||
if (_sWav[wavIndex]._audioStream && _sWav[wavIndex]._audioStream->endOfStream())
|
||||
stopVoice(voiceIndex);
|
||||
}
|
||||
|
||||
return _voice[voiceIndex]._status;
|
||||
}
|
||||
|
||||
void SoundManager::stopVoice(int voiceIndex) {
|
||||
if (_voice[voiceIndex]._status) {
|
||||
_voice[voiceIndex]._status = false;
|
||||
int wavIndex = _voice[voiceIndex]._wavIndex;
|
||||
if (_sWav[wavIndex]._active && _sWav[wavIndex]._freeSampleFl)
|
||||
removeWavSample(wavIndex);
|
||||
}
|
||||
_voice[voiceIndex]._status = false;
|
||||
}
|
||||
|
||||
void SoundManager::playVoice() {
|
||||
if (!_sWav[20]._active)
|
||||
return;
|
||||
|
||||
if (!_voice[2]._status) {
|
||||
int wavIndex = _voice[2]._wavIndex;
|
||||
if (_sWav[wavIndex]._active && _sWav[wavIndex]._freeSampleFl)
|
||||
removeWavSample(wavIndex);
|
||||
}
|
||||
|
||||
playWavSample(2, 20);
|
||||
}
|
||||
|
||||
bool SoundManager::removeWavSample(int wavIndex) {
|
||||
if (!_sWav[wavIndex]._active)
|
||||
return false;
|
||||
|
||||
_vm->_mixer->stopHandle(_sWav[wavIndex]._soundHandle);
|
||||
delete _sWav[wavIndex]._audioStream;
|
||||
_sWav[wavIndex]._audioStream = nullptr;
|
||||
_sWav[wavIndex]._active = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundManager::loadVoice(const Common::Path &filename, size_t fileOffset, size_t entryLength, SwavItem &item) {
|
||||
Common::File f;
|
||||
if (!f.open(filename)) {
|
||||
// Fallback to APC...
|
||||
if (!f.open(setExtension(filename, ".APC"))) {
|
||||
// The English demo doesn't include the speech file.
|
||||
// This avoids it to crash when discussing with other characters
|
||||
if (!_vm->getIsDemo())
|
||||
error("Could not open %s for reading", filename.toString().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
f.seek(fileOffset);
|
||||
item._audioStream = makeSoundStream(f.readStream((entryLength == 0) ? f.size() : entryLength));
|
||||
f.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SoundManager::loadWavSample(int wavIndex, const Common::Path &filename, bool freeSample) {
|
||||
if (_sWav[wavIndex]._active)
|
||||
removeWavSample(wavIndex);
|
||||
|
||||
if (loadVoice(filename, 0, 0, _sWav[wavIndex])) {
|
||||
_sWav[wavIndex]._active = true;
|
||||
_sWav[wavIndex]._freeSampleFl = freeSample;
|
||||
} else{
|
||||
_sWav[wavIndex]._active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::loadWav(const Common::Path &file, int wavIndex) {
|
||||
loadWavSample(wavIndex, file, true);
|
||||
}
|
||||
|
||||
void SoundManager::playWav(int wavIndex) {
|
||||
if (_soundFl || _soundOffFl)
|
||||
return;
|
||||
|
||||
_soundFl = true;
|
||||
_currentSoundIndex = wavIndex;
|
||||
playWavSample(1, wavIndex);
|
||||
}
|
||||
|
||||
void SoundManager::delWav(int wavIndex) {
|
||||
if (!removeWavSample(wavIndex))
|
||||
return;
|
||||
|
||||
if (checkVoiceStatus(1))
|
||||
stopVoice(1);
|
||||
|
||||
_currentSoundIndex = 0;
|
||||
_soundFl = false;
|
||||
}
|
||||
|
||||
void SoundManager::playWavSample(int voiceIndex, int wavIndex) {
|
||||
if (!_sWav[wavIndex]._active)
|
||||
warning("Bad handle");
|
||||
|
||||
if (_voice[voiceIndex]._status && _sWav[wavIndex]._active && _sWav[wavIndex]._freeSampleFl)
|
||||
removeWavSample(wavIndex);
|
||||
|
||||
_voice[voiceIndex]._status = true;
|
||||
_voice[voiceIndex]._wavIndex = wavIndex;
|
||||
|
||||
int volume = (voiceIndex == 2) ? _voiceVolume * 255 / 16 : _soundVolume * 255 / 16;
|
||||
|
||||
// If the handle is still in use, stop it. Otherwise we'll lose the
|
||||
// handle to that sound. This can currently happen (but probably
|
||||
// shouldn't) when skipping a movie.
|
||||
if (_vm->_mixer->isSoundHandleActive(_sWav[wavIndex]._soundHandle))
|
||||
_vm->_mixer->stopHandle(_sWav[wavIndex]._soundHandle);
|
||||
|
||||
// Start the voice playing
|
||||
_sWav[wavIndex]._audioStream->rewind();
|
||||
_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_sWav[wavIndex]._soundHandle,
|
||||
_sWav[wavIndex]._audioStream, -1, volume, 0, DisposeAfterUse::NO);
|
||||
}
|
||||
|
||||
void SoundManager::syncSoundSettings() {
|
||||
bool muteAll = false;
|
||||
if (ConfMan.hasKey("mute"))
|
||||
muteAll = ConfMan.getBool("mute");
|
||||
|
||||
// Update the mute settings
|
||||
_musicOffFl = muteAll || (ConfMan.hasKey("music_mute") && ConfMan.getBool("music_mute"));
|
||||
_soundOffFl = muteAll || (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute"));
|
||||
_voiceOffFl = muteAll || (ConfMan.hasKey("speech_mute") && ConfMan.getBool("speech_mute"));
|
||||
|
||||
// Update the volume levels
|
||||
_musicVolume = MIN(255, ConfMan.getInt("music_volume")) * 16 / 255;
|
||||
_soundVolume = MIN(255, ConfMan.getInt("sfx_volume")) * 16 / 255;
|
||||
_voiceVolume = MIN(255, ConfMan.getInt("speech_volume")) * 16 / 255;
|
||||
|
||||
// Update any active sounds
|
||||
for (int idx = 0; idx < SWAV_COUNT; ++idx) {
|
||||
if (_sWav[idx]._active) {
|
||||
int volume = (idx == 20) ? (_voiceVolume * 255 / 16) : (_soundVolume * 255 / 16);
|
||||
_vm->_mixer->setChannelVolume(_sWav[idx]._soundHandle, volume);
|
||||
}
|
||||
}
|
||||
if (_vm->_mixer->isSoundHandleActive(_musicHandle)) {
|
||||
_vm->_mixer->setChannelVolume(_musicHandle, _musicVolume * 255 / 16);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::updateScummVMSoundSettings() {
|
||||
ConfMan.setBool("mute", _musicOffFl && _soundOffFl && _voiceOffFl);
|
||||
ConfMan.setBool("music_mute", _musicOffFl);
|
||||
ConfMan.setBool("sfx_mute", _soundOffFl);
|
||||
ConfMan.setBool("speech_mute", _voiceOffFl);
|
||||
|
||||
ConfMan.setInt("music_volume", _musicVolume * 255 / 16);
|
||||
ConfMan.setInt("sfx_volume", _soundVolume * 255 / 16);
|
||||
ConfMan.setInt("speech_volume", _voiceVolume * 255 / 16);
|
||||
|
||||
ConfMan.flushToDisk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an audio stream based on a passed raw stream
|
||||
*/
|
||||
Audio::RewindableAudioStream *SoundManager::makeSoundStream(Common::SeekableReadStream *stream) {
|
||||
if (_vm->getPlatform() == Common::kPlatformWindows)
|
||||
return makeAPCStream(stream, DisposeAfterUse::YES);
|
||||
else if (_vm->getPlatform() == Common::kPlatformLinux)
|
||||
return Audio::makeWAVStream(stream, DisposeAfterUse::YES);
|
||||
else
|
||||
return Audio::makeRawStream(stream, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
// Blatant rip from gob engine. Hi DrMcCoy!
|
||||
Common::Path SoundManager::setExtension(const Common::Path &str, const Common::String &ext) {
|
||||
if (str.empty())
|
||||
return str;
|
||||
|
||||
Common::String basename(str.baseName());
|
||||
const char *dot = strrchr(basename.c_str(), '.');
|
||||
if (dot)
|
||||
return str.getParent().appendComponent(Common::String(basename.c_str(), dot - basename.c_str()) + ext);
|
||||
|
||||
return str.append(ext);
|
||||
}
|
||||
} // End of namespace Hopkins
|
||||
151
engines/hopkins/sound.h
Normal file
151
engines/hopkins/sound.h
Normal 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 HOPKINS_SOUND_H
|
||||
#define HOPKINS_SOUND_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
#include "audio/mixer.h"
|
||||
|
||||
namespace Audio {
|
||||
class RewindableAudioStream;
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class VoiceItem {
|
||||
public:
|
||||
VoiceItem() : _status(false), _wavIndex(0) {}
|
||||
|
||||
bool _status;
|
||||
int _wavIndex;
|
||||
};
|
||||
|
||||
class SwavItem {
|
||||
public:
|
||||
SwavItem() : _active(false), _audioStream(NULL), _freeSampleFl(false) {}
|
||||
|
||||
bool _active;
|
||||
Audio::RewindableAudioStream *_audioStream;
|
||||
Audio::SoundHandle _soundHandle;
|
||||
bool _freeSampleFl;
|
||||
};
|
||||
|
||||
class MusicItem {
|
||||
public:
|
||||
MusicItem() : _active(false) {}
|
||||
|
||||
bool _active;
|
||||
};
|
||||
|
||||
class SoundItem {
|
||||
public:
|
||||
SoundItem() : _active(false) {}
|
||||
|
||||
bool _active;
|
||||
};
|
||||
|
||||
#define VOICE_COUNT 3
|
||||
#define SWAV_COUNT 50
|
||||
#define SOUND_COUNT 10
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
class SoundManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
Audio::SoundHandle _musicHandle;
|
||||
int _currentSoundIndex;
|
||||
bool _modPlayingFl;
|
||||
int _oldSoundNumber;
|
||||
|
||||
VoiceItem _voice[VOICE_COUNT];
|
||||
SwavItem _sWav[SWAV_COUNT];
|
||||
SoundItem _sound[SOUND_COUNT];
|
||||
MusicItem _music;
|
||||
|
||||
void playMod(const Common::Path &file);
|
||||
void loadMusic(const Common::Path &file);
|
||||
void playMusic();
|
||||
void stopMusic();
|
||||
void delMusic();
|
||||
bool checkVoiceStatus(int voiceIndex);
|
||||
bool loadVoice(const Common::Path &filename, size_t fileOffset, size_t entryLength, SwavItem &item);
|
||||
void stopVoice(int voiceIndex);
|
||||
void playVoice();
|
||||
void delWav(int wavIndex);
|
||||
void checkVoiceActivity();
|
||||
Common::Path setExtension(const Common::Path &str, const Common::String &ext);
|
||||
Audio::RewindableAudioStream *makeSoundStream(Common::SeekableReadStream *stream);
|
||||
bool removeWavSample(int wavIndex);
|
||||
void loadWavSample(int wavIndex, const Common::Path &filename, bool freeSample);
|
||||
void playWavSample(int voiceIndex, int wavIndex);
|
||||
|
||||
public:
|
||||
bool _musicOffFl;
|
||||
bool _soundOffFl;
|
||||
bool _voiceOffFl;
|
||||
bool _textOffFl;
|
||||
bool _soundFl;
|
||||
bool _skipRefreshFl;
|
||||
int _musicVolume;
|
||||
int _soundVolume;
|
||||
int _voiceVolume;
|
||||
int _specialSoundNum;
|
||||
public:
|
||||
SoundManager(HopkinsEngine *vm);
|
||||
~SoundManager();
|
||||
|
||||
void loadAnimSound();
|
||||
void playAnimSound(int animFrame);
|
||||
|
||||
void loadSample(int wavIndex, const Common::Path &file);
|
||||
void playSample(int wavIndex, int voiceMode = 9);
|
||||
void removeSample(int soundIndex);
|
||||
|
||||
void checkSoundEnd();
|
||||
void checkSounds();
|
||||
void playSoundFile(const Common::Path &file);
|
||||
void playSound(int soundNumber);
|
||||
void stopSound();
|
||||
|
||||
void updateScummVMSoundSettings();
|
||||
void syncSoundSettings();
|
||||
bool mixVoice(int voiceId, int voiceMode, bool displTxtFl = false);
|
||||
|
||||
void setMODMusicVolume(int volume);
|
||||
void setMODSampleVolume();
|
||||
void setMODVoiceVolume();
|
||||
|
||||
void loadWav(const Common::Path &file, int wavIndex);
|
||||
void playWav(int wavIndex);
|
||||
void directPlayWav(const Common::Path &file2);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_SOUND_H */
|
||||
1094
engines/hopkins/talk.cpp
Normal file
1094
engines/hopkins/talk.cpp
Normal file
File diff suppressed because it is too large
Load Diff
77
engines/hopkins/talk.h
Normal file
77
engines/hopkins/talk.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 HOPKINS_TALK_H
|
||||
#define HOPKINS_TALK_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/path.h"
|
||||
|
||||
namespace Hopkins {
|
||||
|
||||
class HopkinsEngine;
|
||||
|
||||
#define MIN_LETTERS_PER_LINE 65
|
||||
|
||||
class TalkManager {
|
||||
private:
|
||||
HopkinsEngine *_vm;
|
||||
|
||||
Common::Path _questionsFilename;
|
||||
Common::Path _answersFilename;
|
||||
byte *_characterBuffer;
|
||||
byte *_characterPalette;
|
||||
size_t _characterSize;
|
||||
int _dialogueMesgId1, _dialogueMesgId2;
|
||||
int _dialogueMesgId3, _dialogueMesgId4;
|
||||
int _paletteBufferIdx;
|
||||
|
||||
void getStringFromBuffer(int srcStart, Common::Path &dest, const char *srcData);
|
||||
int dialogQuestion(bool animatedFl);
|
||||
int dialogAnswer(int idx, bool animatedFl);
|
||||
void searchCharacterPalette(int startIdx, bool dark);
|
||||
void dialogWait();
|
||||
void dialogTalk();
|
||||
void dialogEndTalk();
|
||||
void startCharacterAnim0(int startIndedx, bool readOnlyFl);
|
||||
void initCharacterAnim();
|
||||
void clearCharacterAnim();
|
||||
bool searchCharacterAnim(int idx, const byte *bufPerso, int animId, int bufferSize);
|
||||
int countBoxLines(int idx, const Common::Path &file);
|
||||
void dialogAnim();
|
||||
void displayBobDialogAnim(int idx);
|
||||
|
||||
public:
|
||||
byte *_characterAnim;
|
||||
byte *_characterSprite;
|
||||
|
||||
TalkManager(HopkinsEngine *vm);
|
||||
|
||||
void startStaticCharacterDialogue(const Common::Path &filename);
|
||||
void startAnimatedCharacterDialogue(const Common::Path &filename);
|
||||
void animateObject(const Common::Path &filename);
|
||||
void handleAnswer(int zone, int verb);
|
||||
void handleForestAnswser(int zone, int verb);
|
||||
};
|
||||
|
||||
} // End of namespace Hopkins
|
||||
|
||||
#endif /* HOPKINS_TALK_H */
|
||||
Reference in New Issue
Block a user