Initial commit
This commit is contained in:
1
engines/voyeur/POTFILES
Normal file
1
engines/voyeur/POTFILES
Normal file
@@ -0,0 +1 @@
|
||||
engines/voyeur/metaengine.cpp
|
||||
510
engines/voyeur/animation.cpp
Normal file
510
engines/voyeur/animation.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
/* 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 "voyeur/animation.h"
|
||||
#include "voyeur/staticres.h"
|
||||
#include "voyeur/voyeur.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/system.h"
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
// Number of audio frames to keep audio track topped up when playing back video
|
||||
#define SOUND_FRAMES_READAHEAD 3
|
||||
|
||||
RL2Decoder::RL2Decoder() {
|
||||
_paletteStart = 0;
|
||||
_fileStream = nullptr;
|
||||
_soundFrameNumber = -1;
|
||||
|
||||
_audioTrack = nullptr;
|
||||
_videoTrack = nullptr;
|
||||
}
|
||||
|
||||
RL2Decoder::~RL2Decoder() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool RL2Decoder::loadVideo(int videoId) {
|
||||
Common::Path filename(Common::String::format("%s.rl2",
|
||||
::Voyeur::SZ_FILENAMES[videoId * 2]));
|
||||
return loadRL2File(filename, false);
|
||||
}
|
||||
|
||||
bool RL2Decoder::loadRL2File(const Common::Path &file, bool palFlag) {
|
||||
bool result = VideoDecoder::loadFile(file);
|
||||
_paletteStart = palFlag ? 0 : 128;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RL2Decoder::loadStream(Common::SeekableReadStream *stream) {
|
||||
close();
|
||||
|
||||
// Load basic file information
|
||||
_fileStream = stream;
|
||||
_header.load(stream);
|
||||
_paletteStart = 0;
|
||||
|
||||
// Check RL2 magic number
|
||||
if (!_header.isValid()) {
|
||||
warning("RL2Decoder::loadStream(): attempted to load non-RL2 data (0x%08X)", _header._signature);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add an audio track if sound is present
|
||||
_audioTrack = nullptr;
|
||||
if (_header._soundRate) {
|
||||
_audioTrack = new RL2AudioTrack(_header, stream, getSoundType());
|
||||
addTrack(_audioTrack);
|
||||
}
|
||||
|
||||
// Create a video track
|
||||
_videoTrack = new RL2VideoTrack(_header, _audioTrack, stream);
|
||||
addTrack(_videoTrack);
|
||||
|
||||
// Load the offset/sizes of the video's audio data
|
||||
_soundFrames.reserve(_header._numFrames);
|
||||
for (int frameNumber = 0; frameNumber < _header._numFrames; ++frameNumber) {
|
||||
int offset = _header._frameOffsets[frameNumber];
|
||||
int size = _header._frameSoundSizes[frameNumber];
|
||||
|
||||
_soundFrames.push_back(SoundFrame(offset, size));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const Common::List<Common::Rect> *RL2Decoder::getDirtyRects() const {
|
||||
if (_videoTrack)
|
||||
return _videoTrack->getDirtyRects();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RL2Decoder::clearDirtyRects() {
|
||||
if (_videoTrack)
|
||||
_videoTrack->clearDirtyRects();
|
||||
}
|
||||
|
||||
void RL2Decoder::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) {
|
||||
if (_videoTrack)
|
||||
_videoTrack->copyDirtyRectsToBuffer(dst, pitch);
|
||||
}
|
||||
|
||||
void RL2Decoder::readNextPacket() {
|
||||
int frameNumber = getCurFrame();
|
||||
RL2AudioTrack *audioTrack = getRL2AudioTrack();
|
||||
|
||||
// Handle queueing sound data
|
||||
if (_soundFrameNumber == -1)
|
||||
_soundFrameNumber = (frameNumber == -1) ? 0 : frameNumber;
|
||||
|
||||
while (audioTrack->numQueuedStreams() < SOUND_FRAMES_READAHEAD &&
|
||||
(_soundFrameNumber < (int)_soundFrames.size())) {
|
||||
_fileStream->seek(_soundFrames[_soundFrameNumber]._offset);
|
||||
audioTrack->queueSound(_fileStream, _soundFrames[_soundFrameNumber]._size);
|
||||
++_soundFrameNumber;
|
||||
}
|
||||
}
|
||||
|
||||
bool RL2Decoder::seekIntern(const Audio::Timestamp &where) {
|
||||
_soundFrameNumber = -1;
|
||||
return VideoDecoder::seekIntern(where);
|
||||
}
|
||||
|
||||
void RL2Decoder::close() {
|
||||
VideoDecoder::close();
|
||||
delete _fileStream;
|
||||
_fileStream = nullptr;
|
||||
_soundFrameNumber = -1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
RL2Decoder::SoundFrame::SoundFrame(int offset, int size) {
|
||||
_offset = offset;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
RL2Decoder::RL2FileHeader::RL2FileHeader() {
|
||||
_frameOffsets = nullptr;
|
||||
_frameSoundSizes = nullptr;
|
||||
|
||||
_channels = 0;
|
||||
_colorCount = 0;
|
||||
_numFrames = 0;
|
||||
_rate = 0;
|
||||
_soundRate = 0;
|
||||
_videoBase = 0;
|
||||
_backSize = 0;
|
||||
_signature = MKTAG('N', 'O', 'N', 'E');
|
||||
_form = 0;
|
||||
_dataSize = 0;
|
||||
_method = 0;
|
||||
_defSoundSize = 0;
|
||||
}
|
||||
|
||||
RL2Decoder::RL2FileHeader::~RL2FileHeader() {
|
||||
delete[] _frameOffsets;
|
||||
delete[] _frameSoundSizes;
|
||||
}
|
||||
|
||||
void RL2Decoder::RL2FileHeader::load(Common::SeekableReadStream *stream) {
|
||||
stream->seek(0);
|
||||
|
||||
_form = stream->readUint32LE();
|
||||
_backSize = stream->readUint32LE();
|
||||
_signature = stream->readUint32BE();
|
||||
|
||||
if (!isValid())
|
||||
return;
|
||||
|
||||
_dataSize = stream->readUint32LE();
|
||||
_numFrames = stream->readUint32LE();
|
||||
_method = stream->readUint16LE();
|
||||
_soundRate = stream->readUint16LE();
|
||||
_rate = stream->readUint16LE();
|
||||
_channels = stream->readUint16LE();
|
||||
_defSoundSize = stream->readUint16LE();
|
||||
_videoBase = stream->readUint16LE();
|
||||
_colorCount = stream->readUint32LE();
|
||||
assert(_colorCount <= 256);
|
||||
|
||||
stream->read(_palette, 768);
|
||||
|
||||
// Skip over background frame, if any, and the list of overall frame sizes (which we don't use)
|
||||
stream->skip(_backSize + 4 * _numFrames);
|
||||
|
||||
// Load frame offsets
|
||||
delete[] _frameOffsets;
|
||||
_frameOffsets = new uint32[_numFrames];
|
||||
for (int i = 0; i < _numFrames; ++i)
|
||||
_frameOffsets[i] = stream->readUint32LE();
|
||||
|
||||
// Load the size of the sound portion of each frame
|
||||
delete[] _frameSoundSizes;
|
||||
_frameSoundSizes = new int[_numFrames];
|
||||
for (int i = 0; i < _numFrames; ++i)
|
||||
_frameSoundSizes[i] = stream->readUint32LE() & 0xffff;
|
||||
}
|
||||
|
||||
bool RL2Decoder::RL2FileHeader::isValid() const {
|
||||
return _signature == MKTAG('R','L','V','2') || _signature == MKTAG('R','L','V','3');
|
||||
}
|
||||
|
||||
Common::Rational RL2Decoder::RL2FileHeader::getFrameRate() const {
|
||||
return (_soundRate > 0) ? Common::Rational(_rate, _defSoundSize) :
|
||||
Common::Rational(11025, 1103);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
RL2Decoder::RL2VideoTrack::RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack,
|
||||
Common::SeekableReadStream *stream): _header(header), _fileStream(stream) {
|
||||
|
||||
_frameOffsets = nullptr;
|
||||
|
||||
// Set up surfaces
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
|
||||
_backSurface = nullptr;
|
||||
|
||||
_hasBackFrame = header._backSize != 0;
|
||||
if (_hasBackFrame)
|
||||
initBackSurface();
|
||||
|
||||
_videoBase = header._videoBase;
|
||||
_dirtyPalette = header._colorCount > 0;
|
||||
|
||||
_curFrame = -1;
|
||||
_initialFrame = true;
|
||||
}
|
||||
|
||||
RL2Decoder::RL2VideoTrack::~RL2VideoTrack() {
|
||||
// Free surfaces
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
if (_backSurface) {
|
||||
_backSurface->free();
|
||||
delete _backSurface;
|
||||
}
|
||||
}
|
||||
|
||||
void RL2Decoder::RL2VideoTrack::initBackSurface() {
|
||||
_backSurface = new Graphics::Surface();
|
||||
_backSurface->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
|
||||
}
|
||||
|
||||
bool RL2Decoder::RL2VideoTrack::seek(const Audio::Timestamp &time) {
|
||||
int frame = getFrameAtTime(time);
|
||||
|
||||
if (frame < 0 || frame >= _header._numFrames)
|
||||
return false;
|
||||
|
||||
_curFrame = frame;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16 RL2Decoder::RL2VideoTrack::getWidth() const {
|
||||
return _surface->w;
|
||||
}
|
||||
|
||||
uint16 RL2Decoder::RL2VideoTrack::getHeight() const {
|
||||
return _surface->h;
|
||||
}
|
||||
|
||||
Graphics::PixelFormat RL2Decoder::RL2VideoTrack::getPixelFormat() const {
|
||||
return _surface->format;
|
||||
}
|
||||
|
||||
const Graphics::Surface *RL2Decoder::RL2VideoTrack::decodeNextFrame() {
|
||||
if (_initialFrame && _hasBackFrame) {
|
||||
// Read in the initial background frame
|
||||
_fileStream->seek(0x324);
|
||||
rl2DecodeFrameWithoutTransparency(0);
|
||||
|
||||
Common::copy((byte *)_surface->getPixels(), (byte *)_surface->getPixels() + (320 * 200),
|
||||
(byte *)_backSurface->getPixels());
|
||||
_dirtyRects.push_back(Common::Rect(0, 0, _surface->w, _surface->h));
|
||||
_initialFrame = false;
|
||||
}
|
||||
|
||||
// Move to the next frame data
|
||||
_fileStream->seek(_header._frameOffsets[++_curFrame]);
|
||||
|
||||
// If there's any sound data, pass it to the audio track
|
||||
_fileStream->seek(_header._frameSoundSizes[_curFrame], SEEK_CUR);
|
||||
|
||||
// Decode the graphic data using the appropriate method depending on whether the animation
|
||||
// has a background or just raw frames without any background transparency
|
||||
if (_backSurface) {
|
||||
rl2DecodeFrameWithTransparency(_videoBase);
|
||||
} else {
|
||||
rl2DecodeFrameWithoutTransparency(_videoBase);
|
||||
}
|
||||
|
||||
return _surface;
|
||||
}
|
||||
|
||||
void RL2Decoder::RL2VideoTrack::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) {
|
||||
for (const auto &r : _dirtyRects) {
|
||||
for (int y = r.top; y < r.bottom; ++y) {
|
||||
const int x = r.left;
|
||||
memcpy(dst + y * pitch + x, (byte *)_surface->getPixels() + y * getWidth() + x, r.right - x);
|
||||
}
|
||||
}
|
||||
|
||||
clearDirtyRects();
|
||||
}
|
||||
|
||||
void RL2Decoder::RL2VideoTrack::copyFrame(uint8 *data) {
|
||||
memcpy((byte *)_surface->getPixels(), data, getWidth() * getHeight());
|
||||
|
||||
// Redraw
|
||||
_dirtyRects.clear();
|
||||
_dirtyRects.push_back(Common::Rect(0, 0, getWidth(), getHeight()));
|
||||
}
|
||||
|
||||
void RL2Decoder::RL2VideoTrack::rl2DecodeFrameWithoutTransparency(int screenOffset) {
|
||||
if (screenOffset == -1)
|
||||
screenOffset = _videoBase;
|
||||
int frameSize = _surface->w * _surface->h - screenOffset;
|
||||
byte *destP = (byte *)_surface->getPixels();
|
||||
|
||||
// Main frame decode loop
|
||||
byte nextByte;
|
||||
for (;;) {
|
||||
nextByte = _fileStream->readByte();
|
||||
|
||||
if (nextByte < 0x80) {
|
||||
// Simple byte to copy to output
|
||||
assert(frameSize > 0);
|
||||
*destP++ = nextByte;
|
||||
--frameSize;
|
||||
} else if (nextByte > 0x80) {
|
||||
// Lower 7 bits a run length for the following byte
|
||||
int runLength = _fileStream->readByte();
|
||||
runLength = MIN(runLength, frameSize);
|
||||
|
||||
Common::fill(destP, destP + runLength, nextByte & 0x7f);
|
||||
destP += runLength;
|
||||
frameSize -= runLength;
|
||||
} else {
|
||||
// Follow byte run length for zeroes. If zero, indicates end of image
|
||||
int runLength = _fileStream->readByte();
|
||||
if (runLength == 0)
|
||||
break;
|
||||
|
||||
runLength = MIN(runLength, frameSize);
|
||||
Common::fill(destP, destP + runLength, 0);
|
||||
destP += runLength;
|
||||
frameSize -= runLength;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's any remaining screen area, zero it out
|
||||
byte *endP = (byte *)_surface->getPixels() + _surface->w * _surface->h;
|
||||
if (destP != endP)
|
||||
Common::fill(destP, endP, 0);
|
||||
}
|
||||
|
||||
void RL2Decoder::RL2VideoTrack::rl2DecodeFrameWithTransparency(int screenOffset) {
|
||||
int frameSize = _surface->w * _surface->h - screenOffset;
|
||||
byte *refP = (byte *)_backSurface->getPixels();
|
||||
byte *destP = (byte *)_surface->getPixels();
|
||||
|
||||
// If there's a screen offset, copy unchanged initial pixels from reference surface
|
||||
if (screenOffset > 0)
|
||||
Common::copy(refP, refP + screenOffset, destP);
|
||||
|
||||
// Main decode loop
|
||||
while (frameSize > 0) {
|
||||
byte nextByte = _fileStream->readByte();
|
||||
|
||||
if (nextByte == 0) {
|
||||
// Move one single byte from reference surface
|
||||
assert(frameSize > 0);
|
||||
destP[screenOffset] = refP[screenOffset];
|
||||
++screenOffset;
|
||||
--frameSize;
|
||||
} else if (nextByte < 0x80) {
|
||||
// Single 7-bit pixel to output (128-255)
|
||||
assert(frameSize > 0);
|
||||
destP[screenOffset] = nextByte | 0x80;
|
||||
++screenOffset;
|
||||
--frameSize;
|
||||
} else if (nextByte == 0x80) {
|
||||
int runLength = _fileStream->readByte();
|
||||
if (runLength == 0)
|
||||
return;
|
||||
|
||||
// Run length of transparency (i.e. pixels to copy from reference frame)
|
||||
runLength = MIN(runLength, frameSize);
|
||||
|
||||
Common::copy(refP + screenOffset, refP + screenOffset + runLength, destP + screenOffset);
|
||||
screenOffset += runLength;
|
||||
frameSize -= runLength;
|
||||
} else {
|
||||
// Run length of a single pixel value
|
||||
int runLength = _fileStream->readByte();
|
||||
runLength = MIN(runLength, frameSize);
|
||||
|
||||
Common::fill(destP + screenOffset, destP + screenOffset + runLength, nextByte);
|
||||
screenOffset += runLength;
|
||||
frameSize -= runLength;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a remaining section of the screen not covered, copy it from reference surface
|
||||
if (screenOffset < (_surface->w * _surface->h))
|
||||
Common::copy(refP + screenOffset, refP + (_surface->w * _surface->h), destP + screenOffset);
|
||||
}
|
||||
|
||||
Graphics::Surface *RL2Decoder::RL2VideoTrack::getBackSurface() {
|
||||
if (!_backSurface)
|
||||
initBackSurface();
|
||||
|
||||
return _backSurface;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
RL2Decoder::RL2AudioTrack::RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream, Audio::Mixer::SoundType soundType) :
|
||||
AudioTrack(soundType),
|
||||
_header(header) {
|
||||
// Create audio straem for the audio track
|
||||
_audStream = Audio::makeQueuingAudioStream(_header._rate, _header._channels == 2);
|
||||
}
|
||||
|
||||
RL2Decoder::RL2AudioTrack::~RL2AudioTrack() {
|
||||
delete _audStream;
|
||||
}
|
||||
|
||||
void RL2Decoder::RL2AudioTrack::queueSound(Common::SeekableReadStream *stream, int size) {
|
||||
// Queue the sound data
|
||||
byte *data = (byte *)malloc(size);
|
||||
stream->read(data, size);
|
||||
Common::MemoryReadStream *memoryStream = new Common::MemoryReadStream(data, size,
|
||||
DisposeAfterUse::YES);
|
||||
|
||||
_audStream->queueAudioStream(Audio::makeRawStream(memoryStream, _header._rate,
|
||||
Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
Audio::AudioStream *RL2Decoder::RL2AudioTrack::getAudioStream() const {
|
||||
return _audStream;
|
||||
}
|
||||
|
||||
void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
|
||||
byte *frames, byte *imgPos) {
|
||||
vm->flipPageAndWait();
|
||||
int paletteStart = getPaletteStart();
|
||||
int paletteCount = getPaletteCount();
|
||||
|
||||
PictureResource videoFrame(getRL2VideoTrack()->getBackSurface());
|
||||
int picCtr = 0;
|
||||
|
||||
Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
|
||||
keymapper->getKeymap("voyeur-default")->setEnabled(false);
|
||||
keymapper->getKeymap("cutscene")->setEnabled(true);
|
||||
|
||||
while (!vm->shouldQuit() && !endOfVideo() && !vm->_eventsManager->_mouseClicked) {
|
||||
if (hasDirtyPalette()) {
|
||||
const byte *palette = getPalette();
|
||||
|
||||
vm->_screen->setPalette128(palette, paletteStart, paletteCount);
|
||||
}
|
||||
|
||||
if (needsUpdate()) {
|
||||
if (frames) {
|
||||
// If reached a point where a new background is needed, load it
|
||||
// and copy over to the video decoder
|
||||
if (getCurFrame() >= READ_LE_UINT16(frames + picCtr * 4)) {
|
||||
PictureResource *newPic = vm->_bVoy->boltEntry(0x302 + picCtr)._picResource;
|
||||
Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32,
|
||||
READ_LE_UINT16(imgPos + 4 * picCtr + 2) - 20);
|
||||
|
||||
vm->_screen->sDrawPic(newPic, &videoFrame, pt);
|
||||
++picCtr;
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the next frame and display
|
||||
const Graphics::Surface *frame = decodeNextFrame();
|
||||
vm->_screen->blitFrom(*frame);
|
||||
}
|
||||
|
||||
vm->_eventsManager->getMouseInfo();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
keymapper->getKeymap("cutscene")->setEnabled(false);
|
||||
keymapper->getKeymap("voyeur-default")->setEnabled(true);
|
||||
}
|
||||
|
||||
} // End of namespace Voyeur
|
||||
194
engines/voyeur/animation.h
Normal file
194
engines/voyeur/animation.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/* 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 VOYEUR_ANIMATION_H
|
||||
#define VOYEUR_ANIMATION_H
|
||||
|
||||
#include "video/video_decoder.h"
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "common/array.h"
|
||||
#include "common/list.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/stream.h"
|
||||
#include "voyeur/files.h"
|
||||
|
||||
namespace Audio {
|
||||
class Timestamp;
|
||||
}
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
class VoyeurEngine;
|
||||
|
||||
/**
|
||||
* Decoder for RL2 videos.
|
||||
*
|
||||
* Video decoder used in engines:
|
||||
* - voyeur
|
||||
*/
|
||||
class RL2Decoder : public Video::VideoDecoder {
|
||||
private:
|
||||
class RL2FileHeader {
|
||||
public:
|
||||
RL2FileHeader();
|
||||
~RL2FileHeader();
|
||||
|
||||
int _channels;
|
||||
int _colorCount;
|
||||
int _numFrames;
|
||||
int _rate;
|
||||
int _soundRate;
|
||||
int _videoBase;
|
||||
int *_frameSoundSizes;
|
||||
|
||||
uint32 _backSize;
|
||||
uint32 _signature;
|
||||
uint32 *_frameOffsets;
|
||||
|
||||
byte _palette[768];
|
||||
|
||||
void load(Common::SeekableReadStream *stream);
|
||||
Common::Rational getFrameRate() const;
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
uint32 _form; // Unused variable
|
||||
uint32 _dataSize; // Unused variable
|
||||
int _method; // Unused variable
|
||||
int _defSoundSize;
|
||||
};
|
||||
|
||||
class SoundFrame {
|
||||
public:
|
||||
int _offset;
|
||||
int _size;
|
||||
|
||||
SoundFrame(int offset, int size);
|
||||
};
|
||||
|
||||
class RL2AudioTrack : public AudioTrack {
|
||||
private:
|
||||
const RL2FileHeader &_header;
|
||||
Audio::QueuingAudioStream *_audStream;
|
||||
protected:
|
||||
Audio::AudioStream *getAudioStream() const override;
|
||||
public:
|
||||
RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream,
|
||||
Audio::Mixer::SoundType soundType);
|
||||
~RL2AudioTrack() override;
|
||||
|
||||
int numQueuedStreams() const { return _audStream->numQueuedStreams(); }
|
||||
bool isSeekable() const override { return true; }
|
||||
bool seek(const Audio::Timestamp &time) override { return true; }
|
||||
|
||||
void queueSound(Common::SeekableReadStream *stream, int size);
|
||||
};
|
||||
|
||||
class RL2VideoTrack : public FixedRateVideoTrack {
|
||||
public:
|
||||
RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack,
|
||||
Common::SeekableReadStream *stream);
|
||||
~RL2VideoTrack() override;
|
||||
|
||||
uint16 getWidth() const override;
|
||||
uint16 getHeight() const override;
|
||||
Graphics::Surface *getSurface() { return _surface; }
|
||||
Graphics::Surface *getBackSurface();
|
||||
Graphics::PixelFormat getPixelFormat() const override;
|
||||
int getCurFrame() const override { return _curFrame; }
|
||||
int getFrameCount() const override { return _header._numFrames; }
|
||||
const Graphics::Surface *decodeNextFrame() override;
|
||||
const byte *getPalette() const override { _dirtyPalette = false; return _header._palette; }
|
||||
int getPaletteCount() const { return _header._colorCount; }
|
||||
bool hasDirtyPalette() const override { return _dirtyPalette; }
|
||||
const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; }
|
||||
void clearDirtyRects() { _dirtyRects.clear(); }
|
||||
void copyDirtyRectsToBuffer(uint8 *dst, uint pitch);
|
||||
|
||||
Common::Rational getFrameRate() const override { return _header.getFrameRate(); }
|
||||
bool isSeekable() const override { return true; }
|
||||
bool seek(const Audio::Timestamp &time) override;
|
||||
private:
|
||||
Common::SeekableReadStream *_fileStream;
|
||||
const RL2FileHeader &_header;
|
||||
Graphics::Surface *_surface;
|
||||
Graphics::Surface *_backSurface;
|
||||
bool _hasBackFrame;
|
||||
|
||||
mutable bool _dirtyPalette;
|
||||
|
||||
bool _initialFrame;
|
||||
int _curFrame;
|
||||
uint32 _videoBase;
|
||||
uint32 *_frameOffsets;
|
||||
|
||||
Common::List<Common::Rect> _dirtyRects;
|
||||
|
||||
void copyFrame(uint8 *data);
|
||||
void rl2DecodeFrameWithTransparency(int screenOffset);
|
||||
void rl2DecodeFrameWithoutTransparency(int screenOffset = -1);
|
||||
void initBackSurface();
|
||||
};
|
||||
|
||||
private:
|
||||
RL2AudioTrack *_audioTrack;
|
||||
RL2VideoTrack *_videoTrack;
|
||||
Common::SeekableReadStream *_fileStream;
|
||||
RL2FileHeader _header;
|
||||
int _paletteStart;
|
||||
Common::Array<SoundFrame> _soundFrames;
|
||||
int _soundFrameNumber;
|
||||
const Common::List<Common::Rect> *getDirtyRects() const;
|
||||
|
||||
void clearDirtyRects();
|
||||
void copyDirtyRectsToBuffer(uint8 *dst, uint pitch);
|
||||
int getPaletteStart() const { return _paletteStart; }
|
||||
const RL2FileHeader &getHeader() { return _header; }
|
||||
void readNextPacket() override;
|
||||
bool seekIntern(const Audio::Timestamp &time) override;
|
||||
|
||||
public:
|
||||
RL2Decoder();
|
||||
~RL2Decoder() override;
|
||||
|
||||
void close() override;
|
||||
|
||||
bool loadStream(Common::SeekableReadStream *stream) override;
|
||||
bool loadRL2File(const Common::Path &file, bool palFlag);
|
||||
bool loadVideo(int videoId);
|
||||
int getPaletteCount() const { return _header._colorCount; }
|
||||
|
||||
/**
|
||||
* Play back a given Voyeur RL2 video
|
||||
* @param vm Engine reference
|
||||
* @param resourceOffset Starting resource to use for frame pictures
|
||||
* @param frames Optional frame numbers resource for when to apply image data
|
||||
* @param imgPos Position to draw image data
|
||||
*/
|
||||
void play(VoyeurEngine *vm, int resourceOffset = 0, byte *frames = nullptr, byte *imgPos = nullptr);
|
||||
RL2VideoTrack *getRL2VideoTrack() { return _videoTrack; }
|
||||
RL2AudioTrack *getRL2AudioTrack() { return _audioTrack; }
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif /* VOYEUR_ANIMATION_H */
|
||||
3
engines/voyeur/configure.engine
Normal file
3
engines/voyeur/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 voyeur "Voyeur" yes
|
||||
4
engines/voyeur/credits.pl
Normal file
4
engines/voyeur/credits.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
begin_section("Voyeur");
|
||||
add_person("Arnaud Boutonné", "Strangerke", "");
|
||||
add_person("Paul Gilbert", "dreammaster", "");
|
||||
end_section();
|
||||
370
engines/voyeur/data.cpp
Normal file
370
engines/voyeur/data.cpp
Normal file
@@ -0,0 +1,370 @@
|
||||
/* 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 "voyeur/data.h"
|
||||
#include "voyeur/voyeur.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
void VoyeurEvent::synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_hour);
|
||||
s.syncAsByte(_minute);
|
||||
s.syncAsByte(_isAM);
|
||||
s.syncAsByte(_type);
|
||||
s.syncAsSint16LE(_audioVideoId);
|
||||
s.syncAsSint16LE(_computerOn);
|
||||
s.syncAsSint16LE(_computerOff);
|
||||
s.syncAsSint16LE(_dead);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
SVoy::SVoy(VoyeurEngine *vm):_vm(vm) {
|
||||
// Initialize all the data fields
|
||||
_abortInterface = false;
|
||||
_isAM = false;
|
||||
Common::fill(&_phoneCallsReceived[0], &_phoneCallsReceived[5], false);
|
||||
Common::fill(&_roomHotspotsEnabled[0], &_roomHotspotsEnabled[32], false);
|
||||
_victimMurdered = false;
|
||||
|
||||
_audioVisualStartTime = 0;
|
||||
_audioVisualDuration = 0;
|
||||
_boltGroupId2 = 0;
|
||||
_computerTextId = -1;
|
||||
_computerTimeMin = _computerTimeMax = 0;
|
||||
_eventCount = 0;
|
||||
_fadingStep1 = 0;
|
||||
_fadingStep2 = 0;
|
||||
_fadingType = 0;
|
||||
_incriminatedVictimNumber = 0;
|
||||
_musicStartTime = 0;
|
||||
_playStampMode = 0;
|
||||
_switchBGNum = 0;
|
||||
_transitionId = 0;
|
||||
_videoEventId = 0;
|
||||
_vocSecondsOffset = 0;
|
||||
_RTANum = 0;
|
||||
_RTVLimit = 0;
|
||||
_RTVNum = 0;
|
||||
_viewBounds = nullptr;
|
||||
Common::fill(&_evPicPtrs[0], &_evPicPtrs[6], (PictureResource *)nullptr);
|
||||
Common::fill(&_evCmPtrs[0], &_evCmPtrs[6], (CMapResource *)nullptr);
|
||||
_policeEvent = 0;
|
||||
|
||||
_eventFlags = EVTFLAG_TIME_DISABLED;
|
||||
_fadingAmount1 = _fadingAmount2 = 127;
|
||||
_murderThreshold = 9999;
|
||||
_aptLoadMode = -1;
|
||||
_eventFlags |= EVTFLAG_100;
|
||||
_totalPhoneCalls = 0;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
_evPicPtrs[i] = nullptr;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
_events[i]._hour = 0;
|
||||
_events[i]._minute = 0;
|
||||
_events[i]._isAM = true;
|
||||
_events[i]._type = EVTYPE_NONE;
|
||||
_events[i]._audioVideoId = -1;
|
||||
_events[i]._computerOn = 0;
|
||||
_events[i]._computerOff = 0;
|
||||
_events[i]._dead = 0;
|
||||
}
|
||||
for (int i = 0; i < 6; i++)
|
||||
_evCmPtrs[i] = nullptr;
|
||||
}
|
||||
|
||||
void SVoy::addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId,
|
||||
int on, int off, int dead) {
|
||||
VoyeurEvent &e = _events[_eventCount++];
|
||||
|
||||
e._type = type;
|
||||
e._hour = hour;
|
||||
e._minute = minute;
|
||||
e._isAM = hour < 12;
|
||||
e._audioVideoId = audioVideoId;
|
||||
e._computerOn = on;
|
||||
e._computerOff = off;
|
||||
e._dead = dead;
|
||||
}
|
||||
|
||||
void SVoy::synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_isAM);
|
||||
s.syncAsSint16LE(_RTANum);
|
||||
s.syncAsSint16LE(_RTVNum);
|
||||
s.syncAsSint16LE(_switchBGNum);
|
||||
|
||||
_videoHotspotTimes.synchronize(s);
|
||||
_audioHotspotTimes.synchronize(s);
|
||||
_evidenceHotspotTimes.synchronize(s);
|
||||
|
||||
int count = s.getVersion() == 1 ? 20 : 32;
|
||||
for (int idx = 0; idx < count; ++idx) {
|
||||
s.syncAsByte(_roomHotspotsEnabled[idx]);
|
||||
}
|
||||
|
||||
s.syncAsSint16LE(_audioVisualStartTime);
|
||||
s.syncAsSint16LE(_audioVisualDuration);
|
||||
s.syncAsSint16LE(_vocSecondsOffset);
|
||||
s.syncAsSint16LE(_abortInterface);
|
||||
s.syncAsSint16LE(_playStampMode);
|
||||
s.syncAsSint16LE(_aptLoadMode);
|
||||
s.syncAsSint16LE(_transitionId);
|
||||
s.syncAsSint16LE(_RTVLimit);
|
||||
s.syncAsSint16LE(_eventFlags);
|
||||
s.syncAsSint16LE(_boltGroupId2);
|
||||
|
||||
s.syncAsSint16LE(_musicStartTime);
|
||||
s.syncAsSint16LE(_totalPhoneCalls);
|
||||
s.syncAsSint16LE(_computerTextId);
|
||||
s.syncAsSint16LE(_computerTimeMin);
|
||||
s.syncAsSint16LE(_computerTimeMax);
|
||||
s.syncAsSint16LE(_victimMurdered);
|
||||
s.syncAsSint16LE(_murderThreshold);
|
||||
|
||||
// Events
|
||||
s.syncAsUint16LE(_eventCount);
|
||||
for (int idx = 0; idx < _eventCount; ++idx)
|
||||
_events[idx].synchronize(s);
|
||||
|
||||
s.syncAsSint16LE(_fadingAmount1);
|
||||
s.syncAsSint16LE(_fadingAmount2);
|
||||
s.syncAsSint16LE(_fadingStep1);
|
||||
s.syncAsSint16LE(_fadingStep2);
|
||||
s.syncAsSint16LE(_fadingType);
|
||||
s.skip(sizeof(int16), 0, 2);
|
||||
s.syncAsSint16LE(_incriminatedVictimNumber);
|
||||
s.syncAsSint16LE(_videoEventId);
|
||||
|
||||
if (s.isLoading()) {
|
||||
// Reset apartment loading mode to initial game value
|
||||
_aptLoadMode = 140;
|
||||
_viewBounds = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SVoy::addVideoEventStart() {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._hour = _vm->_gameHour;
|
||||
e._minute = _vm->_gameMinute;
|
||||
e._isAM = _isAM;
|
||||
e._type = EVTYPE_VIDEO;
|
||||
e._audioVideoId = _vm->_audioVideoId;
|
||||
e._computerOn = _vocSecondsOffset;
|
||||
e._dead = _vm->_eventsManager->_videoDead;
|
||||
}
|
||||
|
||||
void SVoy::addVideoEventEnd() {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._computerOff = _RTVNum - _audioVisualStartTime - _vocSecondsOffset;
|
||||
if (_eventCount < (TOTAL_EVENTS - 1))
|
||||
++_eventCount;
|
||||
}
|
||||
|
||||
void SVoy::addAudioEventStart() {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._hour = _vm->_gameHour;
|
||||
e._minute = _vm->_gameMinute;
|
||||
e._isAM = _isAM;
|
||||
e._type = EVTYPE_AUDIO;
|
||||
e._audioVideoId = _vm->_audioVideoId;
|
||||
e._computerOn = _vocSecondsOffset;
|
||||
e._dead = _vm->_eventsManager->_videoDead;
|
||||
}
|
||||
|
||||
void SVoy::addAudioEventEnd() {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._computerOff = _RTVNum - _audioVisualStartTime - _vocSecondsOffset;
|
||||
if (_eventCount < (TOTAL_EVENTS - 1))
|
||||
++_eventCount;
|
||||
}
|
||||
|
||||
void SVoy::addEvidEventStart(int v) {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._hour = _vm->_gameHour;
|
||||
e._minute = _vm->_gameMinute;
|
||||
e._isAM = _isAM;
|
||||
e._type = EVTYPE_EVID;
|
||||
e._audioVideoId = _vm->_playStampGroupId;
|
||||
e._computerOn = _boltGroupId2;
|
||||
e._computerOff = v;
|
||||
}
|
||||
|
||||
void SVoy::addEvidEventEnd(int totalPages) {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._dead = totalPages;
|
||||
if (_eventCount < (TOTAL_EVENTS - 1))
|
||||
++_eventCount;
|
||||
}
|
||||
|
||||
void SVoy::addComputerEventStart() {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._hour = _vm->_gameHour;
|
||||
e._minute = _vm->_gameMinute;
|
||||
e._isAM = _isAM;
|
||||
e._type = EVTYPE_COMPUTER;
|
||||
e._audioVideoId = _vm->_playStampGroupId;
|
||||
e._computerOn = _computerTextId;
|
||||
}
|
||||
|
||||
void SVoy::addComputerEventEnd(int v) {
|
||||
VoyeurEvent &e = _events[_eventCount];
|
||||
e._computerOff = v;
|
||||
if (_eventCount < (TOTAL_EVENTS - 1))
|
||||
++_eventCount;
|
||||
}
|
||||
|
||||
void SVoy::reviewAnEvidEvent(int eventIndex) {
|
||||
VoyeurEvent &e = _events[eventIndex];
|
||||
_vm->_playStampGroupId = e._audioVideoId;
|
||||
_boltGroupId2 = e._computerOn;
|
||||
int frameOff = e._computerOff;
|
||||
|
||||
if (_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId)) {
|
||||
_vm->_screen->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
|
||||
_vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
|
||||
_vm->_screen->_vPort->setupViewPort(_vm->_screen->_backgroundPage);
|
||||
_vm->_screen->_backColors->startFade();
|
||||
|
||||
_vm->doEvidDisplay(frameOff, e._dead);
|
||||
_vm->_bVoy->freeBoltGroup(_vm->_playStampGroupId);
|
||||
_vm->_playStampGroupId = -1;
|
||||
|
||||
if (_boltGroupId2 != -1) {
|
||||
_vm->_bVoy->freeBoltGroup(_boltGroupId2);
|
||||
_boltGroupId2 = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SVoy::reviewComputerEvent(int eventIndex) {
|
||||
VoyeurEvent &e = _events[eventIndex];
|
||||
_vm->_playStampGroupId = e._audioVideoId;
|
||||
_computerTextId = e._computerOn;
|
||||
|
||||
if (_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId)) {
|
||||
_vm->_screen->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
|
||||
_vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
|
||||
_vm->_screen->_vPort->setupViewPort(_vm->_screen->_backgroundPage);
|
||||
_vm->_screen->_backColors->startFade();
|
||||
_vm->flipPageAndWaitForFade();
|
||||
|
||||
_vm->getComputerBrush();
|
||||
_vm->flipPageAndWait();
|
||||
_vm->doComputerText(e._computerOff);
|
||||
|
||||
_vm->_bVoy->freeBoltGroup(0x4900);
|
||||
_vm->_bVoy->freeBoltGroup(_vm->_playStampGroupId);
|
||||
_vm->_playStampGroupId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool SVoy::checkForKey() {
|
||||
StateResource *state = _vm->_controlPtr->_state;
|
||||
state->_victimEvidenceIndex = 0;
|
||||
if (_vm->_voy->_victimMurdered)
|
||||
return false;
|
||||
|
||||
for (int eventIdx = 0; eventIdx < _eventCount; ++eventIdx) {
|
||||
VoyeurEvent &e = _events[eventIdx];
|
||||
|
||||
switch (e._type) {
|
||||
case EVTYPE_VIDEO:
|
||||
switch (state->_victimIndex) {
|
||||
case 1:
|
||||
if (e._audioVideoId == 33 && e._computerOn < 2 && e._computerOff >= 38)
|
||||
state->_victimEvidenceIndex = 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (e._audioVideoId == 47 && e._computerOn < 2 && e._computerOff >= 9)
|
||||
state->_victimEvidenceIndex = 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (e._audioVideoId == 46 && e._computerOn < 2 && e._computerOff > 2)
|
||||
state->_victimEvidenceIndex = 3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (e._audioVideoId == 40 && e._computerOn < 2 && e._computerOff > 6)
|
||||
state->_victimEvidenceIndex = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVTYPE_AUDIO:
|
||||
switch (state->_victimIndex) {
|
||||
case 1:
|
||||
if (e._audioVideoId == 8 && e._computerOn < 2 && e._computerOff > 26)
|
||||
state->_victimEvidenceIndex = 1;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (e._audioVideoId == 20 && e._computerOn < 2 && e._computerOff > 28)
|
||||
state->_victimEvidenceIndex = 3;
|
||||
if (e._audioVideoId == 35 && e._computerOn < 2 && e._computerOff > 18)
|
||||
state->_victimEvidenceIndex = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVTYPE_EVID:
|
||||
switch (state->_victimIndex) {
|
||||
case 4:
|
||||
if (e._audioVideoId == 0x2400 && e._computerOn == 0x4f00 && e._computerOff == 17)
|
||||
state->_victimEvidenceIndex = 4;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVTYPE_COMPUTER:
|
||||
switch (state->_victimIndex) {
|
||||
case 2:
|
||||
if (e._computerOn == 13 && e._computerOff > 76)
|
||||
state->_victimEvidenceIndex = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (state->_victimEvidenceIndex == state->_victimIndex)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Voyeur
|
||||
230
engines/voyeur/data.h
Normal file
230
engines/voyeur/data.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/* 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 VOYEUR_DATA_H
|
||||
#define VOYEUR_DATA_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
#include "voyeur/files.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
#define TOTAL_EVENTS 1000
|
||||
|
||||
enum VoyeurEventType {
|
||||
EVTYPE_NONE = 0,
|
||||
EVTYPE_VIDEO = 1,
|
||||
EVTYPE_AUDIO = 2,
|
||||
EVTYPE_EVID = 3,
|
||||
EVTYPE_COMPUTER = 4
|
||||
};
|
||||
|
||||
enum EventFlag { EVTFLAG_TIME_DISABLED = 1, EVTFLAG_2 = 2, EVTFLAG_8 = 8, EVTFLAG_RECORDING = 0x10,
|
||||
EVTFLAG_40 = 0x40, EVTFLAG_VICTIM_PRESET = 0x80, EVTFLAG_100 = 0x100 };
|
||||
|
||||
struct VoyeurEvent {
|
||||
int _hour;
|
||||
int _minute;
|
||||
bool _isAM;
|
||||
VoyeurEventType _type;
|
||||
int _audioVideoId;
|
||||
int _computerOn;
|
||||
int _computerOff;
|
||||
int _dead;
|
||||
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
class VoyeurEngne;
|
||||
|
||||
/**
|
||||
* Encapsulates a list of the time expired ranges that hotspots in the mansion
|
||||
* view are enabled for in a given time period.
|
||||
*/
|
||||
template<int SLOTS>
|
||||
class HotspotTimes {
|
||||
public:
|
||||
int _min[SLOTS][20]; // Min time expired
|
||||
int _max[SLOTS][20]; // Max time expired
|
||||
|
||||
HotspotTimes() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the data to an initial state
|
||||
*/
|
||||
void reset() {
|
||||
for (int hotspotIdx = 0; hotspotIdx < 20; ++hotspotIdx) {
|
||||
for (int slotIdx = 0; slotIdx < SLOTS; ++slotIdx) {
|
||||
_min[slotIdx][hotspotIdx] = 9999;
|
||||
_max[slotIdx][hotspotIdx] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronise the data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) {
|
||||
for (int slotIndex = 0; slotIndex < SLOTS; ++slotIndex) {
|
||||
for (int hotspotIndex = 0; hotspotIndex < 20; ++hotspotIndex) {
|
||||
s.syncAsSint16LE(_min[slotIndex][hotspotIndex]);
|
||||
s.syncAsSint16LE(_max[slotIndex][hotspotIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given value is in the range specified by the
|
||||
* min and max at the given hotspot and slot indexes
|
||||
*/
|
||||
bool isInRange(int slotIndex, int hotspotIndex, int v) const {
|
||||
return _min[slotIndex][hotspotIndex] <= v &&
|
||||
v < _max[slotIndex][hotspotIndex];
|
||||
}
|
||||
};
|
||||
|
||||
class SVoy {
|
||||
private:
|
||||
VoyeurEngine *_vm;
|
||||
|
||||
public:
|
||||
bool _abortInterface;
|
||||
bool _isAM;
|
||||
bool _phoneCallsReceived[5];
|
||||
bool _roomHotspotsEnabled[32];
|
||||
bool _victimMurdered;
|
||||
|
||||
int _aptLoadMode;
|
||||
int _audioVisualStartTime;
|
||||
int _audioVisualDuration;
|
||||
int _boltGroupId2;
|
||||
int _computerTextId;
|
||||
int _computerTimeMin;
|
||||
int _computerTimeMax;
|
||||
int _eventCount;
|
||||
int _eventFlags;
|
||||
int _fadingAmount1;
|
||||
int _fadingAmount2;
|
||||
int _fadingStep1;
|
||||
int _fadingStep2;
|
||||
int _fadingType;
|
||||
int _incriminatedVictimNumber;
|
||||
int _murderThreshold;
|
||||
int _musicStartTime;
|
||||
int _playStampMode;
|
||||
int _switchBGNum;
|
||||
int _totalPhoneCalls;
|
||||
int _transitionId;
|
||||
int _videoEventId;
|
||||
int _vocSecondsOffset;
|
||||
int _RTANum;
|
||||
int _RTVLimit;
|
||||
int _RTVNum;
|
||||
|
||||
HotspotTimes<3> _audioHotspotTimes;
|
||||
HotspotTimes<3> _evidenceHotspotTimes;
|
||||
HotspotTimes<8> _videoHotspotTimes;
|
||||
|
||||
Common::Rect _computerScreenRect;
|
||||
RectResource *_viewBounds;
|
||||
PictureResource *_evPicPtrs[6];
|
||||
CMapResource *_evCmPtrs[6];
|
||||
VoyeurEvent _events[TOTAL_EVENTS];
|
||||
|
||||
SVoy(VoyeurEngine *vm);
|
||||
|
||||
/**
|
||||
* Synchronize the data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Add an event to the list of game events that have occurred
|
||||
*/
|
||||
void addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId,
|
||||
int on, int off, int dead);
|
||||
|
||||
/**
|
||||
* Adds the start of a video event happening
|
||||
*/
|
||||
void addVideoEventStart();
|
||||
|
||||
/**
|
||||
* Adds the finish of a video event happening
|
||||
*/
|
||||
void addVideoEventEnd();
|
||||
|
||||
/**
|
||||
* Adds the start of an audio event happening
|
||||
*/
|
||||
void addAudioEventStart();
|
||||
|
||||
/**
|
||||
* Adsd the finish of an audio event happening
|
||||
*/
|
||||
void addAudioEventEnd();
|
||||
|
||||
/**
|
||||
* Adds the start of an evidence event happening
|
||||
*/
|
||||
void addEvidEventStart(int v);
|
||||
|
||||
/**
|
||||
* Adds the finish of an evidence event happening
|
||||
*/
|
||||
void addEvidEventEnd(int totalPages);
|
||||
|
||||
/**
|
||||
* Adds the start of a computer event happening
|
||||
*/
|
||||
void addComputerEventStart();
|
||||
|
||||
/**
|
||||
* Adds the finish of a computer event happening
|
||||
*/
|
||||
void addComputerEventEnd(int v);
|
||||
|
||||
/**
|
||||
* Review a previously recorded evidence event
|
||||
*/
|
||||
void reviewAnEvidEvent(int eventIndex);
|
||||
|
||||
/**
|
||||
* Review a previously recorded computer event
|
||||
*/
|
||||
void reviewComputerEvent(int eventIndex);
|
||||
|
||||
/**
|
||||
* Checks for key information in determining what kind of murder
|
||||
* should take place
|
||||
*/
|
||||
bool checkForKey();
|
||||
|
||||
private:
|
||||
int _policeEvent;
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif /* VOYEUR_DATA_H */
|
||||
173
engines/voyeur/debugger.cpp
Normal file
173
engines/voyeur/debugger.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* 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 "voyeur/debugger.h"
|
||||
#include "voyeur/screen.h"
|
||||
#include "voyeur/voyeur.h"
|
||||
#include "voyeur/staticres.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
Debugger::Debugger(VoyeurEngine *vm) : GUI::Debugger(), _vm(vm) {
|
||||
// Register methods
|
||||
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
|
||||
registerCmd("time", WRAP_METHOD(Debugger, Cmd_Time));
|
||||
registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots));
|
||||
registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse));
|
||||
|
||||
// Set fields
|
||||
_isTimeActive = true;
|
||||
_showMousePosition = false;
|
||||
}
|
||||
|
||||
static const int TIME_STATES[] = {
|
||||
0, 31, 0, 43, 59, 0, 67, 75, 85, 93, 0, 0, 111, 121, 0, 0
|
||||
};
|
||||
|
||||
bool Debugger::Cmd_Time(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
// Get the current day and time of day
|
||||
Common::String dtString = _vm->getDayName();
|
||||
Common::String timeString = _vm->getTimeOfDay();
|
||||
if (!timeString.empty())
|
||||
dtString += " " + timeString;
|
||||
|
||||
debugPrintf("Time period = %d, date/time is: %s, time is %s\n",
|
||||
_vm->_voy->_transitionId, dtString.c_str(), _isTimeActive ? "on" : "off");
|
||||
debugPrintf("Format: %s [on | off | 1..17 | val <amount>]\n\n", argv[0]);
|
||||
} else {
|
||||
if (!strcmp(argv[1], "on")) {
|
||||
_isTimeActive = true;
|
||||
debugPrintf("Time is now on\n\n");
|
||||
} else if (!strcmp(argv[1], "off")) {
|
||||
_isTimeActive = false;
|
||||
debugPrintf("Time is now off\n\n");
|
||||
} else if (!strcmp(argv[1], "val")) {
|
||||
if (argc < 3) {
|
||||
debugPrintf("Time expired is currently %d.\n", _vm->_voy->_RTVNum);
|
||||
} else {
|
||||
_vm->_voy->_RTVNum = atoi(argv[2]);
|
||||
debugPrintf("Time expired is now %d.\n", _vm->_voy->_RTVNum);
|
||||
}
|
||||
} else {
|
||||
int timeId = atoi(argv[1]);
|
||||
if (timeId >= 1 && timeId < 17) {
|
||||
int stateId = TIME_STATES[timeId - 1];
|
||||
if (!stateId) {
|
||||
debugPrintf("Given time period is not used in-game\n");
|
||||
} else {
|
||||
debugPrintf("Changing to time period: %d\n", timeId);
|
||||
if (_vm->_mainThread->goToState(-1, stateId))
|
||||
_vm->_mainThread->parsePlayCommands();
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
debugPrintf("Unknown parameter\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_Hotspots(int argc, const char **argv) {
|
||||
if (_vm->_voy->_computerTextId >= 0) {
|
||||
debugPrintf("Hotspot Computer Screen %d - %d,%d->%d,%d\n",
|
||||
_vm->_voy->_computerTextId,
|
||||
_vm->_voy->_computerScreenRect.left,
|
||||
_vm->_voy->_computerScreenRect.top,
|
||||
_vm->_voy->_computerScreenRect.right,
|
||||
_vm->_voy->_computerScreenRect.bottom);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Room hotspots
|
||||
BoltEntry &boltEntry = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 4);
|
||||
if (boltEntry._rectResource) {
|
||||
Common::Array<RectEntry> &hotspots = boltEntry._rectResource->_entries;
|
||||
for (uint hotspotIdx = 0; hotspotIdx < hotspots.size(); ++hotspotIdx) {
|
||||
Common::String pos = Common::String::format("(%d,%d->%d,%d)",
|
||||
hotspots[hotspotIdx].left, hotspots[hotspotIdx].top,
|
||||
hotspots[hotspotIdx].right, hotspots[hotspotIdx].bottom);
|
||||
int arrIndex = hotspots[hotspotIdx]._arrIndex;
|
||||
if (_vm->_voy->_roomHotspotsEnabled[arrIndex - 1]) {
|
||||
debugPrintf("Hotspot Room %d - %s - Enabled\n", arrIndex, pos);
|
||||
} else {
|
||||
debugPrintf("Hotspot Room - %s - Disabled\n", pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Outside view hotspots
|
||||
BoltEntry &boltEntry = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1);
|
||||
if (boltEntry._rectResource) {
|
||||
Common::Array<RectEntry> &hotspots = boltEntry._rectResource->_entries;
|
||||
|
||||
for (uint hotspotIdx = 0; hotspotIdx < hotspots.size(); ++hotspotIdx) {
|
||||
Common::String pos = Common::String::format("(%d,%d->%d,%d)",
|
||||
hotspots[hotspotIdx].left, hotspots[hotspotIdx].top,
|
||||
hotspots[hotspotIdx].right, hotspots[hotspotIdx].bottom);
|
||||
|
||||
for (int arrIndex = 0; arrIndex < 3; ++arrIndex) {
|
||||
if (_vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx] != 9999) {
|
||||
debugPrintf("Hotspot %d %s Audio slot %d, time: %d to %d\n",
|
||||
hotspotIdx, pos.c_str(), arrIndex,
|
||||
_vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx],
|
||||
_vm->_voy->_audioHotspotTimes._max[arrIndex][hotspotIdx]);
|
||||
}
|
||||
|
||||
if (_vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx] != 9999) {
|
||||
debugPrintf("Hotspot %d %s Evidence slot %d, time: %d to %d\n",
|
||||
hotspotIdx, pos.c_str(), arrIndex,
|
||||
_vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx],
|
||||
_vm->_voy->_evidenceHotspotTimes._max[arrIndex][hotspotIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int arrIndex = 0; arrIndex < 8; ++arrIndex) {
|
||||
if (_vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx] != 9999) {
|
||||
debugPrintf("Hotspot %d %s Video slot %d, time: %d to %d\n",
|
||||
hotspotIdx, pos.c_str(), arrIndex,
|
||||
_vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx],
|
||||
_vm->_voy->_videoHotspotTimes._max[arrIndex][hotspotIdx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugPrintf("\nEnd of list\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_Mouse(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
debugPrintf("mouse [ on | off ]\n");
|
||||
} else {
|
||||
_showMousePosition = !strcmp(argv[1], "on");
|
||||
debugPrintf("Mouse position is now %s\n", _showMousePosition ? "on" : "off");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Voyeur
|
||||
69
engines/voyeur/debugger.h
Normal file
69
engines/voyeur/debugger.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VOYEUR_DEBUGGER_H
|
||||
#define VOYEUR_DEBUGGER_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
class VoyeurEngine;
|
||||
|
||||
class Debugger : public GUI::Debugger {
|
||||
private:
|
||||
VoyeurEngine *_vm;
|
||||
public:
|
||||
/**
|
||||
* Specifies whether time should pass, and the video camera's batteries go down
|
||||
* @default true
|
||||
*/
|
||||
bool _isTimeActive;
|
||||
|
||||
/*
|
||||
* Specifies whether to show the current mouse position on the screen
|
||||
*/
|
||||
bool _showMousePosition;
|
||||
protected:
|
||||
/**
|
||||
* Turn time on or off, set the current time period, or the camera delay
|
||||
* within the current time period.
|
||||
*/
|
||||
bool Cmd_Time(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* List the active hotspots during the current time period
|
||||
*/
|
||||
bool Cmd_Hotspots(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Toggle showing the mouse on the screen
|
||||
*/
|
||||
bool Cmd_Mouse(int argc, const char **argv);
|
||||
public:
|
||||
Debugger(VoyeurEngine *vm);
|
||||
~Debugger() override {}
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif
|
||||
65
engines/voyeur/detection.cpp
Normal file
65
engines/voyeur/detection.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "base/plugins.h"
|
||||
|
||||
#include "common/str-array.h"
|
||||
#include "common/memstream.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "voyeur/detection.h"
|
||||
#include "voyeur/voyeur.h"
|
||||
|
||||
static const PlainGameDescriptor voyeurGames[] = {
|
||||
{"voyeur", "Voyeur"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static const DebugChannelDef debugFlagList[] = {
|
||||
{Voyeur::kDebugScripts, "scripts", "Game scripts"},
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
#include "voyeur/detection_tables.h"
|
||||
|
||||
class VoyeurMetaEngineDetection : public AdvancedMetaEngineDetection<Voyeur::VoyeurGameDescription> {
|
||||
public:
|
||||
VoyeurMetaEngineDetection() : AdvancedMetaEngineDetection(Voyeur::gameDescriptions, voyeurGames) {
|
||||
_maxScanDepth = 3;
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "voyeur";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Voyeur";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Voyeur (C) Philips P.O.V. Entertainment Group";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return debugFlagList;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(VOYEUR_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, VoyeurMetaEngineDetection);
|
||||
37
engines/voyeur/detection.h
Normal file
37
engines/voyeur/detection.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VOYEUR_DETECTION_H
|
||||
#define VOYEUR_DETECTION_H
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
struct VoyeurGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
};
|
||||
|
||||
#define GAMEOPTION_COPY_PROTECTION GUIO_GAMEOPTIONS1
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif // VOYEUR_DETECTION_H
|
||||
64
engines/voyeur/detection_tables.h
Normal file
64
engines/voyeur/detection_tables.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 Voyeur {
|
||||
|
||||
static const VoyeurGameDescription gameDescriptions[] = {
|
||||
{
|
||||
// Voyeur DOS English
|
||||
{
|
||||
"voyeur",
|
||||
nullptr,
|
||||
AD_ENTRY1s("bvoy.blt", "12e9e10654171501cf8be3a7aa7198e1", 13036269),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GUIO_NOMIDI, GAMEOPTION_COPY_PROTECTION)
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
// Voyeur DOS English
|
||||
{
|
||||
"voyeur",
|
||||
"Demo",
|
||||
AD_ENTRY1s("bvoy.blt", "abd10f241b845ebc2a76d27a43770709", 13015827),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GUIO_NOMIDI, GAMEOPTION_COPY_PROTECTION)
|
||||
}
|
||||
},
|
||||
|
||||
{// Voyeur German Fan Translation - By Bakhtosh
|
||||
{
|
||||
"voyeur",
|
||||
"German Fan Made Version",
|
||||
AD_ENTRY1s("bvoy.blt", "af281a228ddcf7daa18a3c8b591bace9", 15134654),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GUIO_NOMIDI, GAMEOPTION_COPY_PROTECTION)}
|
||||
},
|
||||
|
||||
{AD_TABLE_END_MARKER}};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
598
engines/voyeur/events.cpp
Normal file
598
engines/voyeur/events.cpp
Normal file
@@ -0,0 +1,598 @@
|
||||
/* 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 "voyeur/events.h"
|
||||
#include "voyeur/voyeur.h"
|
||||
#include "voyeur/staticres.h"
|
||||
#include "common/events.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "graphics/paletteman.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
IntNode::IntNode() {
|
||||
_intFunc = nullptr;
|
||||
_curTime = 0;
|
||||
_timeReset = 0;
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
IntNode::IntNode(uint16 curTime, uint16 timeReset, uint16 flags) {
|
||||
_intFunc = nullptr;
|
||||
_curTime = curTime;
|
||||
_timeReset = timeReset;
|
||||
_flags = flags;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
IntData::IntData() {
|
||||
_flipWait = false;
|
||||
_hasPalette = false;
|
||||
_flashTimer = 0;
|
||||
_flashStep = 0;
|
||||
_skipFading = false;
|
||||
_palStartIndex = 0;
|
||||
_palEndIndex = 0;
|
||||
_palette = nullptr;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
EventsManager::EventsManager(VoyeurEngine *vm) : _intPtr(_gameData),
|
||||
_fadeIntNode(0, 0, 3), _cycleIntNode(0, 0, 3), _vm(vm) {
|
||||
_cycleStatus = 0;
|
||||
_fadeStatus = 0;
|
||||
_priorFrameTime = g_system->getMillis();
|
||||
_gameCounter = 0;
|
||||
_counterFlag = false;
|
||||
_recordBlinkCounter = 0;
|
||||
_cursorBlinked = false;
|
||||
|
||||
Common::fill(&_cycleTime[0], &_cycleTime[4], 0);
|
||||
Common::fill(&_cycleNext[0], &_cycleNext[4], (byte *)nullptr);
|
||||
_cyclePtr = nullptr;
|
||||
|
||||
_leftClick = _rightClick = false;
|
||||
_mouseClicked = _newMouseClicked = false;
|
||||
_newLeftClick = _newRightClick = false;
|
||||
|
||||
_videoDead = 0;
|
||||
|
||||
_fadeFirstCol = _fadeLastCol = 0;
|
||||
_fadeCount = 1;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
_cycleNext[i] = nullptr;
|
||||
}
|
||||
|
||||
void EventsManager::startMainClockInt() {
|
||||
_mainIntNode._intFunc = &EventsManager::mainVoyeurIntFunc;
|
||||
_mainIntNode._flags = 0;
|
||||
_mainIntNode._curTime = 0;
|
||||
_mainIntNode._timeReset = 60;
|
||||
}
|
||||
|
||||
void EventsManager::mainVoyeurIntFunc() {
|
||||
if (!(_vm->_voy->_eventFlags & EVTFLAG_TIME_DISABLED)) {
|
||||
++_vm->_voy->_switchBGNum;
|
||||
|
||||
if (_vm->_debugger->_isTimeActive) {
|
||||
// Increase camera discharge
|
||||
++_vm->_voy->_RTVNum;
|
||||
|
||||
// If the murder threshold has been set, and is passed, then flag the victim
|
||||
// as murdered, which prevents sending the tape from succeeding
|
||||
if (_vm->_voy->_RTVNum >= _vm->_voy->_murderThreshold)
|
||||
_vm->_voy->_victimMurdered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::sWaitFlip() {
|
||||
Common::Array<ViewPortResource *> &viewPorts = _vm->_screen->_viewPortListPtr->_entries;
|
||||
for (uint idx = 0; idx < viewPorts.size(); ++idx) {
|
||||
ViewPortResource &viewPort = *viewPorts[idx];
|
||||
|
||||
if (_vm->_screen->_saveBack && (viewPort._flags & DISPFLAG_40)) {
|
||||
Common::Rect *clipPtr = _vm->_screen->_clipPtr;
|
||||
_vm->_screen->_clipPtr = &viewPort._clipRect;
|
||||
|
||||
if (viewPort._restoreFn)
|
||||
(_vm->_screen->*viewPort._restoreFn)(&viewPort);
|
||||
|
||||
_vm->_screen->_clipPtr = clipPtr;
|
||||
viewPort._rectListCount[viewPort._pageIndex] = 0;
|
||||
viewPort._rectListPtr[viewPort._pageIndex]->clear();
|
||||
viewPort._flags &= ~DISPFLAG_40;
|
||||
}
|
||||
}
|
||||
|
||||
while (_gameData._flipWait && !_vm->shouldQuit()) {
|
||||
pollEvents();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::checkForNextFrameCounter() {
|
||||
// Check for next game frame
|
||||
uint32 milli = g_system->getMillis();
|
||||
if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
|
||||
_counterFlag = !_counterFlag;
|
||||
if (_counterFlag)
|
||||
++_gameCounter;
|
||||
_priorFrameTime = milli;
|
||||
|
||||
// Run the timer-based updates
|
||||
voyeurTimer();
|
||||
|
||||
if ((_gameCounter % GAME_FRAME_RATE) == 0)
|
||||
mainVoyeurIntFunc();
|
||||
|
||||
// If mouse position display is on, display the position
|
||||
if (_vm->_debugger->_showMousePosition)
|
||||
showMousePosition();
|
||||
|
||||
// Display the frame
|
||||
_vm->_screen->update();
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::showMousePosition() {
|
||||
const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont));
|
||||
Common::String mousePos = Common::String::format("(%d,%d)", _mousePos.x, _mousePos.y);
|
||||
if (_vm->_voyeurArea == AREA_INTERFACE) {
|
||||
Common::Point pt = _mousePos + _vm->_mansionViewPos - Common::Point(40, 27);
|
||||
if (pt.x < 0) pt.x = 0;
|
||||
if (pt.y < 0) pt.y = 0;
|
||||
|
||||
mousePos += Common::String::format(" - (%d,%d)", pt.x, pt.y);
|
||||
}
|
||||
|
||||
_vm->_screen->fillRect(Common::Rect(0, 0, 110, font.getFontHeight()), 0);
|
||||
font.drawString(_vm->_screen, mousePos, 0, 0, 110, 63);
|
||||
}
|
||||
|
||||
void EventsManager::voyeurTimer() {
|
||||
_gameData._flashTimer += _gameData._flashStep;
|
||||
|
||||
if (_gameData._flipWait) {
|
||||
_gameData._flipWait = false;
|
||||
_gameData._skipFading = false;
|
||||
}
|
||||
|
||||
videoTimer();
|
||||
|
||||
// Iterate through the list of registered nodes
|
||||
for (auto &node : _intNodes) {
|
||||
if (node->_flags & 1)
|
||||
continue;
|
||||
if (!(node->_flags & 2)) {
|
||||
if (--node->_curTime != 0)
|
||||
continue;
|
||||
|
||||
node->_curTime = node->_timeReset;
|
||||
}
|
||||
|
||||
(this->*node->_intFunc)();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EventsManager::videoTimer() {
|
||||
if (_gameData._hasPalette) {
|
||||
_gameData._hasPalette = false;
|
||||
|
||||
g_system->getPaletteManager()->setPalette(_gameData._palette +
|
||||
_gameData._palStartIndex * 3, _gameData._palStartIndex,
|
||||
_gameData._palEndIndex - _gameData._palStartIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::delay(int cycles) {
|
||||
uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE;
|
||||
uint32 delayEnd = g_system->getMillis() + totalMilli;
|
||||
|
||||
while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) {
|
||||
g_system->delayMillis(10);
|
||||
|
||||
pollEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::delayClick(int cycles) {
|
||||
uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE;
|
||||
uint32 delayEnd = g_system->getMillis() + totalMilli;
|
||||
|
||||
do {
|
||||
g_system->delayMillis(10);
|
||||
getMouseInfo();
|
||||
} while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd
|
||||
&& !_vm->_eventsManager->_mouseClicked);
|
||||
}
|
||||
|
||||
void EventsManager::pollEvents() {
|
||||
checkForNextFrameCounter();
|
||||
|
||||
Common::Event event;
|
||||
while (g_system->getEventManager()->pollEvent(event) && !_vm->shouldQuit()) {
|
||||
// Handle keypress
|
||||
switch (event.type) {
|
||||
case Common::EVENT_QUIT:
|
||||
case Common::EVENT_RETURN_TO_LAUNCHER:
|
||||
case Common::EVENT_KEYUP:
|
||||
return;
|
||||
|
||||
case Common::EVENT_KEYDOWN:
|
||||
return;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
_newLeftClick = true;
|
||||
_newMouseClicked = true;
|
||||
return;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
_newRightClick = true;
|
||||
_newMouseClicked = true;
|
||||
return;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
_newMouseClicked = false;
|
||||
_newLeftClick = false;
|
||||
_newRightClick = false;
|
||||
return;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
_mousePos = event.mouse;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::startFade(CMapResource *cMap) {
|
||||
_fadeIntNode._flags |= 1;
|
||||
if (_cycleStatus & 1)
|
||||
_cycleIntNode._flags |= 1;
|
||||
|
||||
_fadeFirstCol = cMap->_start;
|
||||
_fadeLastCol = cMap->_end;
|
||||
_fadeCount = cMap->_steps + 1;
|
||||
|
||||
if (cMap->_steps > 0) {
|
||||
_fadeStatus = cMap->_fadeStatus | 1;
|
||||
byte *vgaP = &_vm->_screen->_VGAColors[_fadeFirstCol * 3];
|
||||
int mapIndex = 0;
|
||||
|
||||
for (int idx = _fadeFirstCol; idx <= _fadeLastCol; ++idx, vgaP += 3) {
|
||||
ViewPortPalEntry &palEntry = _vm->_screen->_viewPortListPtr->_palette[idx];
|
||||
palEntry._rEntry = vgaP[0] << 8;
|
||||
int rDiff = (cMap->_entries[mapIndex * 3] << 8) - palEntry._rEntry;
|
||||
palEntry._rChange = rDiff / cMap->_steps;
|
||||
|
||||
palEntry._gEntry = vgaP[1] << 8;
|
||||
int gDiff = (cMap->_entries[mapIndex * 3 + 1] << 8) - palEntry._gEntry;
|
||||
palEntry._gChange = gDiff / cMap->_steps;
|
||||
|
||||
palEntry._bEntry = vgaP[2] << 8;
|
||||
int bDiff = (cMap->_entries[mapIndex * 3 + 2] << 8) - palEntry._bEntry;
|
||||
palEntry._bChange = bDiff / cMap->_steps;
|
||||
|
||||
palEntry._palIndex = idx;
|
||||
if (!(cMap->_fadeStatus & 1))
|
||||
++mapIndex;
|
||||
}
|
||||
|
||||
if (cMap->_fadeStatus & 2)
|
||||
_intPtr._skipFading = true;
|
||||
_fadeIntNode._flags &= ~1;
|
||||
} else {
|
||||
byte *vgaP = &_vm->_screen->_VGAColors[_fadeFirstCol * 3];
|
||||
int mapIndex = 0;
|
||||
|
||||
for (int idx = _fadeFirstCol; idx <= _fadeLastCol; ++idx, vgaP += 3) {
|
||||
Common::copy(&cMap->_entries[mapIndex], &cMap->_entries[mapIndex + 3], vgaP);
|
||||
|
||||
if (!(cMap->_fadeStatus & 1))
|
||||
mapIndex += 3;
|
||||
}
|
||||
|
||||
if (_intPtr._palStartIndex > _fadeFirstCol)
|
||||
_intPtr._palStartIndex = _fadeFirstCol;
|
||||
if (_intPtr._palEndIndex < _fadeLastCol)
|
||||
_intPtr._palEndIndex = _fadeLastCol;
|
||||
|
||||
_intPtr._hasPalette = true;
|
||||
}
|
||||
|
||||
if (_cycleStatus & 1)
|
||||
_cycleIntNode._flags &= ~1;
|
||||
}
|
||||
|
||||
void EventsManager::addIntNode(IntNode *node) {
|
||||
_intNodes.push_back(node);
|
||||
}
|
||||
|
||||
void EventsManager::addFadeInt() {
|
||||
IntNode &node = _fade2IntNode;
|
||||
node._intFunc = &EventsManager::fadeIntFunc;
|
||||
node._flags = 0;
|
||||
node._curTime = 0;
|
||||
node._timeReset = 1;
|
||||
|
||||
addIntNode(&node);
|
||||
}
|
||||
|
||||
void EventsManager::vDoFadeInt() {
|
||||
if (_intPtr._skipFading)
|
||||
return;
|
||||
if (--_fadeCount == 0) {
|
||||
_fadeIntNode._flags |= 1;
|
||||
_fadeStatus &= ~1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = _fadeFirstCol; i <= _fadeLastCol; ++i) {
|
||||
ViewPortPalEntry &palEntry = _vm->_screen->_viewPortListPtr->_palette[i];
|
||||
byte *vgaP = &_vm->_screen->_VGAColors[palEntry._palIndex * 3];
|
||||
|
||||
palEntry._rEntry += palEntry._rChange;
|
||||
palEntry._gEntry += palEntry._gChange;
|
||||
palEntry._bEntry += palEntry._bChange;
|
||||
|
||||
vgaP[0] = palEntry._rEntry >> 8;
|
||||
vgaP[1] = palEntry._gEntry >> 8;
|
||||
vgaP[2] = palEntry._bEntry >> 8;
|
||||
}
|
||||
|
||||
if (_intPtr._palStartIndex > _fadeFirstCol)
|
||||
_intPtr._palStartIndex = _fadeFirstCol;
|
||||
if (_intPtr._palEndIndex < _fadeLastCol)
|
||||
_intPtr._palEndIndex = _fadeLastCol;
|
||||
|
||||
_intPtr._hasPalette = true;
|
||||
}
|
||||
|
||||
void EventsManager::vDoCycleInt() {
|
||||
for (int idx = 3; idx >= 0; --idx) {
|
||||
if (_cyclePtr->_type[idx] && --_cycleTime[idx] <= 0) {
|
||||
byte *pSrc = _cycleNext[idx];
|
||||
byte *pPal = _vm->_screen->_VGAColors;
|
||||
|
||||
if (_cyclePtr->_type[idx] != 1) {
|
||||
// New palette data being specified - loop to set entries
|
||||
do {
|
||||
int palIndex = READ_LE_UINT16(pSrc);
|
||||
pPal[palIndex * 3] = pSrc[3];
|
||||
pPal[palIndex * 3 + 1] = pSrc[4];
|
||||
pPal[palIndex * 3 + 2] = pSrc[5];
|
||||
pSrc += 6;
|
||||
|
||||
if ((int16)READ_LE_UINT16(pSrc) >= 0) {
|
||||
// Resetting back to start of cycle data
|
||||
pSrc = _cycleNext[idx];
|
||||
break;
|
||||
}
|
||||
} while (*(pSrc + 2) == 0);
|
||||
|
||||
_cycleNext[idx] = pSrc;
|
||||
_cycleTime[idx] = pSrc[2];
|
||||
} else {
|
||||
// Palette rotation to be done
|
||||
_cycleTime[idx] = pSrc[4];
|
||||
|
||||
if (pSrc[5] == 1) {
|
||||
// Move palette entry to end of range
|
||||
int start = READ_LE_UINT16(pSrc);
|
||||
int end = READ_LE_UINT16(&pSrc[2]);
|
||||
assert(start < 0x100 && end < 0x100);
|
||||
|
||||
// Store the RGB of the first entry to be moved
|
||||
byte r = pPal[start * 3];
|
||||
byte g = pPal[start * 3 + 1];
|
||||
byte b = pPal[start * 3 + 2];
|
||||
|
||||
Common::copy(&pPal[start * 3 + 3], &pPal[end * 3 + 3], &pPal[start * 3]);
|
||||
|
||||
// Place the original saved entry at the end of the range
|
||||
pPal[end * 3] = r;
|
||||
pPal[end * 3 + 1] = g;
|
||||
pPal[end * 3 + 2] = b;
|
||||
|
||||
if (_fadeStatus & 1) {
|
||||
//dx = start, di = end
|
||||
warning("TODO: Adjustment of ViewPortListResource");
|
||||
}
|
||||
} else {
|
||||
// Move palette entry to start of range
|
||||
int start = READ_LE_UINT16(pSrc);
|
||||
int end = READ_LE_UINT16(&pSrc[2]);
|
||||
assert(start < 0x100 && end < 0x100);
|
||||
|
||||
// Store the RGB of the entry to be moved
|
||||
byte r = pPal[end * 3];
|
||||
byte g = pPal[end * 3 + 1];
|
||||
byte b = pPal[end * 3 + 2];
|
||||
|
||||
// Move the remainder of the range forwards one entry
|
||||
Common::copy_backward(&pPal[start * 3], &pPal[end * 3], &pPal[end * 3 + 3]);
|
||||
|
||||
// Place the original saved entry at the end of the range
|
||||
pPal[start * 3] = r;
|
||||
pPal[start * 3 + 1] = g;
|
||||
pPal[start * 3 + 2] = b;
|
||||
|
||||
if (_fadeStatus & 1) {
|
||||
//dx = start, di = end
|
||||
warning("TODO: Adjustment of ViewPortListResource");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_intPtr._hasPalette = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EventsManager::fadeIntFunc() {
|
||||
switch (_vm->_voy->_fadingType) {
|
||||
case 1:
|
||||
if (_vm->_voy->_fadingAmount1 < 63)
|
||||
_vm->_voy->_fadingAmount1 += _vm->_voy->_fadingStep1;
|
||||
if (_vm->_voy->_fadingAmount2 < 63)
|
||||
_vm->_voy->_fadingAmount2 += _vm->_voy->_fadingStep2;
|
||||
if (_vm->_voy->_fadingAmount1 > 63)
|
||||
_vm->_voy->_fadingAmount1 = 63;
|
||||
if (_vm->_voy->_fadingAmount2 > 63)
|
||||
_vm->_voy->_fadingAmount2 = 63;
|
||||
if ((_vm->_voy->_fadingAmount1 == 63) && (_vm->_voy->_fadingAmount2 == 63))
|
||||
_vm->_voy->_fadingType = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (_vm->_voy->_fadingAmount1 > 0)
|
||||
_vm->_voy->_fadingAmount1 -= _vm->_voy->_fadingStep1;
|
||||
if (_vm->_voy->_fadingAmount2 > 0)
|
||||
_vm->_voy->_fadingAmount2 -= _vm->_voy->_fadingStep2;
|
||||
if (_vm->_voy->_fadingAmount1 < 0)
|
||||
_vm->_voy->_fadingAmount1 = 0;
|
||||
if (_vm->_voy->_fadingAmount2 < 0)
|
||||
_vm->_voy->_fadingAmount2 = 0;
|
||||
if ((_vm->_voy->_fadingAmount1 == 0) && (_vm->_voy->_fadingAmount2 == 0))
|
||||
_vm->_voy->_fadingType = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::deleteIntNode(IntNode *node) {
|
||||
_intNodes.remove(node);
|
||||
}
|
||||
|
||||
void EventsManager::vInitColor() {
|
||||
_fadeIntNode._intFunc = &EventsManager::vDoFadeInt;
|
||||
_cycleIntNode._intFunc = &EventsManager::vDoCycleInt;
|
||||
|
||||
addIntNode(&_fadeIntNode);
|
||||
addIntNode(&_cycleIntNode);
|
||||
}
|
||||
|
||||
void EventsManager::setCursor(PictureResource *pic) {
|
||||
PictureResource cursor;
|
||||
cursor._bounds = pic->_bounds;
|
||||
cursor._flags = DISPFLAG_CURSOR;
|
||||
|
||||
_vm->_screen->sDrawPic(pic, &cursor, Common::Point());
|
||||
}
|
||||
|
||||
void EventsManager::setCursor(byte *cursorData, int width, int height, int keyColor) {
|
||||
CursorMan.replaceCursor(cursorData, width, height, width / 2, height / 2, keyColor);
|
||||
}
|
||||
|
||||
void EventsManager::setCursorColor(int idx, int mode) {
|
||||
switch (mode) {
|
||||
case 0:
|
||||
_vm->_screen->setColor(idx, 90, 90, 232);
|
||||
break;
|
||||
case 1:
|
||||
_vm->_screen->setColor(idx, 232, 90, 90);
|
||||
break;
|
||||
case 2:
|
||||
_vm->_screen->setColor(idx, 90, 232, 90);
|
||||
break;
|
||||
case 3:
|
||||
_vm->_screen->setColor(idx, 90, 232, 232);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::showCursor() {
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void EventsManager::hideCursor() {
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
void EventsManager::getMouseInfo() {
|
||||
pollEvents();
|
||||
|
||||
if (_vm->_voy->_eventFlags & EVTFLAG_RECORDING) {
|
||||
if ((_gameCounter - _recordBlinkCounter) > 8) {
|
||||
_recordBlinkCounter = _gameCounter;
|
||||
|
||||
if (_cursorBlinked) {
|
||||
_cursorBlinked = false;
|
||||
_vm->_screen->setOneColor(128, 220, 20, 20);
|
||||
_vm->_screen->setColor(128, 220, 20, 20);
|
||||
} else {
|
||||
_cursorBlinked = true;
|
||||
_vm->_screen->setOneColor(128, 220, 220, 220);
|
||||
_vm->_screen->setColor(128, 220, 220, 220);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_mouseClicked = _newMouseClicked;
|
||||
_leftClick = _newLeftClick;
|
||||
_rightClick = _newRightClick;
|
||||
|
||||
_newMouseClicked = false;
|
||||
_newLeftClick = false;
|
||||
_newRightClick = false;
|
||||
}
|
||||
|
||||
void EventsManager::startCursorBlink() {
|
||||
if (_vm->_voy->_eventFlags & EVTFLAG_RECORDING) {
|
||||
_vm->_screen->setOneColor(128, 55, 5, 5);
|
||||
_vm->_screen->setColor(128, 220, 20, 20);
|
||||
_intPtr._hasPalette = true;
|
||||
|
||||
_vm->_screen->drawDot();
|
||||
//copySection();
|
||||
}
|
||||
}
|
||||
|
||||
void EventsManager::incrementTime(int amt) {
|
||||
for (int i = 0; i < amt; ++i)
|
||||
mainVoyeurIntFunc();
|
||||
}
|
||||
|
||||
void EventsManager::stopEvidDim() {
|
||||
deleteIntNode(&_evIntNode);
|
||||
}
|
||||
|
||||
Common::String EventsManager::getEvidString(int eventIndex) {
|
||||
assert(eventIndex <= _vm->_voy->_eventCount);
|
||||
VoyeurEvent &e = _vm->_voy->_events[eventIndex];
|
||||
|
||||
if (_vm->getLanguage() == Common::DE_DEU)
|
||||
return Common::String::format("%03d %.2d:%.2d %s %s", eventIndex + 1,
|
||||
e._isAM ? e._hour : e._hour + 12, e._minute, e._isAM ? AM_DE : PM_DE, EVENT_TYPE_STRINGS_DE[e._type - 1]);
|
||||
|
||||
return Common::String::format("%03d %.2d:%.2d %s %s", eventIndex + 1,
|
||||
e._hour, e._minute, e._isAM ? AM_EN : PM_EN, EVENT_TYPE_STRINGS_EN[e._type - 1]);
|
||||
}
|
||||
|
||||
} // End of namespace Voyeur
|
||||
144
engines/voyeur/events.h
Normal file
144
engines/voyeur/events.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VOYEUR_EVENTS_H
|
||||
#define VOYEUR_EVENTS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/list.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "voyeur/files.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
class VoyeurEngine;
|
||||
class EventsManager;
|
||||
class CMapResource;
|
||||
|
||||
#define GAME_FRAME_RATE 50
|
||||
#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
|
||||
|
||||
typedef void (EventsManager::*EventMethodPtr)();
|
||||
|
||||
class IntNode {
|
||||
public:
|
||||
EventMethodPtr _intFunc;
|
||||
uint16 _curTime;
|
||||
uint16 _timeReset;
|
||||
uint32 _flags;
|
||||
|
||||
IntNode();
|
||||
IntNode(uint16 curTime, uint16 timeReset, uint16 flags);
|
||||
};
|
||||
|
||||
class IntData {
|
||||
public:
|
||||
bool _flipWait;
|
||||
int _flashTimer;
|
||||
int _flashStep;
|
||||
bool _hasPalette;
|
||||
bool _skipFading;
|
||||
int _palStartIndex;
|
||||
int _palEndIndex;
|
||||
byte *_palette;
|
||||
|
||||
IntData();
|
||||
};
|
||||
|
||||
class EventsManager {
|
||||
private:
|
||||
VoyeurEngine *_vm;
|
||||
bool _counterFlag;
|
||||
bool _cursorBlinked;
|
||||
uint32 _gameCounter;
|
||||
uint32 _priorFrameTime;
|
||||
uint32 _recordBlinkCounter; // Original field was called _joe :)
|
||||
Common::List<IntNode *> _intNodes;
|
||||
Common::Point _mousePos;
|
||||
|
||||
void mainVoyeurIntFunc();
|
||||
void checkForNextFrameCounter();
|
||||
void voyeurTimer();
|
||||
void videoTimer();
|
||||
void vDoFadeInt();
|
||||
void vDoCycleInt();
|
||||
void fadeIntFunc();
|
||||
void addIntNode(IntNode *node);
|
||||
void deleteIntNode(IntNode *node);
|
||||
|
||||
/**
|
||||
* Debugger support method to show the mouse position
|
||||
*/
|
||||
void showMousePosition();
|
||||
public:
|
||||
IntData _gameData;
|
||||
IntData &_intPtr;
|
||||
IntNode _fadeIntNode;
|
||||
IntNode _fade2IntNode;
|
||||
IntNode _cycleIntNode;
|
||||
IntNode _evIntNode;
|
||||
IntNode _mainIntNode;
|
||||
int _cycleStatus;
|
||||
int _fadeFirstCol, _fadeLastCol;
|
||||
int _fadeCount;
|
||||
int _fadeStatus;
|
||||
|
||||
bool _leftClick, _rightClick;
|
||||
bool _mouseClicked, _newMouseClicked;
|
||||
bool _newLeftClick, _newRightClick;
|
||||
|
||||
int _videoDead;
|
||||
int _cycleTime[4];
|
||||
byte *_cycleNext[4];
|
||||
VInitCycleResource *_cyclePtr;
|
||||
|
||||
EventsManager(VoyeurEngine *vm);
|
||||
|
||||
void setMousePos(const Common::Point &p) { _mousePos = p; }
|
||||
void startMainClockInt();
|
||||
void sWaitFlip();
|
||||
void vInitColor();
|
||||
|
||||
void delay(int cycles);
|
||||
void delayClick(int cycles);
|
||||
void pollEvents();
|
||||
void startFade(CMapResource *cMap);
|
||||
void addFadeInt();
|
||||
|
||||
void setCursor(PictureResource *pic);
|
||||
void setCursor(byte *cursorData, int width, int height, int keyColor);
|
||||
void setCursorColor(int idx, int mode);
|
||||
void showCursor();
|
||||
void hideCursor();
|
||||
Common::Point getMousePos() { return _mousePos; }
|
||||
uint32 getGameCounter() const { return _gameCounter; }
|
||||
void getMouseInfo();
|
||||
void startCursorBlink();
|
||||
void incrementTime(int amt);
|
||||
|
||||
void stopEvidDim();
|
||||
|
||||
Common::String getEvidString(int eventIndex);
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif /* VOYEUR_EVENTS_H */
|
||||
1634
engines/voyeur/files.cpp
Normal file
1634
engines/voyeur/files.cpp
Normal file
File diff suppressed because it is too large
Load Diff
618
engines/voyeur/files.h
Normal file
618
engines/voyeur/files.h
Normal file
@@ -0,0 +1,618 @@
|
||||
/* 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 VOYEUR_FILES_H
|
||||
#define VOYEUR_FILES_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/file.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
#include "voyeur/screen.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
class VoyeurEngine;
|
||||
class BoltFile;
|
||||
class BoltGroup;
|
||||
class BoltEntry;
|
||||
class RectResource;
|
||||
class PictureResource;
|
||||
class ViewPortResource;
|
||||
class ViewPortListResource;
|
||||
class FontResource;
|
||||
class CMapResource;
|
||||
class VInitCycleResource;
|
||||
class PtrResource;
|
||||
class ControlResource;
|
||||
class StateResource;
|
||||
class ThreadResource;
|
||||
|
||||
#define DECOMPRESS_SIZE 0x7000
|
||||
|
||||
class ResolveEntry {
|
||||
public:
|
||||
uint32 _id;
|
||||
byte **_p;
|
||||
|
||||
ResolveEntry(uint32 id, byte **p) { _id = id; _p = p; }
|
||||
};
|
||||
|
||||
class BoltFilesState {
|
||||
public:
|
||||
VoyeurEngine *_vm;
|
||||
BoltFile *_curLibPtr;
|
||||
BoltGroup *_curGroupPtr;
|
||||
BoltEntry *_curMemberPtr;
|
||||
int _bufferEnd;
|
||||
int _bufferBegin;
|
||||
int _bytesLeft;
|
||||
int _bufSize;
|
||||
byte *_bufStart;
|
||||
byte *_bufPos;
|
||||
byte _decompressBuf[DECOMPRESS_SIZE];
|
||||
int _historyIndex;
|
||||
byte _historyBuffer[0x200];
|
||||
int _runLength;
|
||||
bool _decompState;
|
||||
int _runType;
|
||||
int _runValue;
|
||||
int _runOffset;
|
||||
Common::File *_curFd;
|
||||
Common::Array<ResolveEntry> _resolves;
|
||||
|
||||
byte *_boltPageFrame;
|
||||
public:
|
||||
BoltFilesState(VoyeurEngine *vm);
|
||||
|
||||
byte *decompress(byte *buf, int size, int mode);
|
||||
void nextBlock();
|
||||
};
|
||||
|
||||
class BoltFile {
|
||||
private:
|
||||
Common::Array<BoltGroup> _groups;
|
||||
protected:
|
||||
BoltFilesState &_state;
|
||||
|
||||
virtual void initResource(int resType) = 0;
|
||||
void initDefault();
|
||||
private:
|
||||
void resolveAll();
|
||||
byte *getBoltMember(uint32 id);
|
||||
|
||||
public:
|
||||
Common::File _file;
|
||||
|
||||
BoltFile(const char *filename, BoltFilesState &state);
|
||||
virtual ~BoltFile();
|
||||
|
||||
BoltGroup *getBoltGroup(uint16 id);
|
||||
void freeBoltGroup(uint16 id);
|
||||
void freeBoltMember(uint32 id);
|
||||
byte *memberAddr(uint32 id);
|
||||
byte *memberAddrOffset(uint32 id);
|
||||
void resolveIt(uint32 id, byte **p);
|
||||
void resolveFunction(uint32 id, ScreenMethodPtr *fn);
|
||||
|
||||
BoltEntry &boltEntry(uint16 id);
|
||||
BoltEntry &getBoltEntryFromLong(uint32 id);
|
||||
PictureResource *getPictureResource(uint32 id);
|
||||
CMapResource *getCMapResource(uint32 id);
|
||||
};
|
||||
|
||||
class BVoyBoltFile: public BoltFile {
|
||||
private:
|
||||
// initType method table
|
||||
void sInitRect();
|
||||
void sInitPic();
|
||||
void vInitCMap();
|
||||
void vInitCycl();
|
||||
void initViewPort();
|
||||
void initViewPortList();
|
||||
void initFontInfo();
|
||||
void initFont();
|
||||
void initSoundMap();
|
||||
protected:
|
||||
void initResource(int resType) override;
|
||||
public:
|
||||
BVoyBoltFile(BoltFilesState &state);
|
||||
};
|
||||
|
||||
class StampBoltFile: public BoltFile {
|
||||
private:
|
||||
void initThread();
|
||||
void initState();
|
||||
void initPtr();
|
||||
void initControl();
|
||||
protected:
|
||||
void initResource(int resType) override;
|
||||
public:
|
||||
StampBoltFile(BoltFilesState &state);
|
||||
};
|
||||
|
||||
class BoltGroup {
|
||||
private:
|
||||
Common::SeekableReadStream *_file;
|
||||
public:
|
||||
bool _loaded;
|
||||
bool _processed;
|
||||
int _count;
|
||||
int _fileOffset;
|
||||
Common::Array<BoltEntry> _entries;
|
||||
public:
|
||||
BoltGroup(Common::SeekableReadStream *f);
|
||||
virtual ~BoltGroup();
|
||||
|
||||
void load(uint16 groupId);
|
||||
void unload();
|
||||
};
|
||||
|
||||
|
||||
class BoltEntry {
|
||||
private:
|
||||
Common::SeekableReadStream *_file;
|
||||
public:
|
||||
uint16 _id;
|
||||
byte _mode;
|
||||
byte _initMethod;
|
||||
int _fileOffset;
|
||||
int _size;
|
||||
byte *_data;
|
||||
|
||||
// bvoy.blt resource types
|
||||
RectResource *_rectResource;
|
||||
PictureResource *_picResource;
|
||||
ViewPortResource *_viewPortResource;
|
||||
ViewPortListResource *_viewPortListResource;
|
||||
FontResource *_fontResource;
|
||||
FontInfoResource *_fontInfoResource;
|
||||
CMapResource *_cMapResource;
|
||||
VInitCycleResource *_vInitCycleResource;
|
||||
|
||||
// stampblt.blt resource types
|
||||
PtrResource *_ptrResource;
|
||||
ControlResource *_controlResource;
|
||||
StateResource *_stateResource;
|
||||
ThreadResource *_threadResource;
|
||||
public:
|
||||
BoltEntry(Common::SeekableReadStream *f, uint16 id);
|
||||
virtual ~BoltEntry();
|
||||
|
||||
void load();
|
||||
bool hasResource() const;
|
||||
};
|
||||
|
||||
class FilesManager {
|
||||
public:
|
||||
BoltFilesState *_boltFilesState;
|
||||
BoltFile *_curLibPtr;
|
||||
public:
|
||||
FilesManager(VoyeurEngine *vm);
|
||||
~FilesManager();
|
||||
|
||||
bool openBoltLib(const char *filename, BoltFile *&boltFile);
|
||||
byte *fload(const char *filename, int *size);
|
||||
};
|
||||
|
||||
class RectEntry: public Common::Rect {
|
||||
public:
|
||||
int _arrIndex;
|
||||
int _count;
|
||||
|
||||
RectEntry(int x1, int y1, int x2, int y2, int arrIndex, int count);
|
||||
};
|
||||
|
||||
class RectResource: public Common::Rect {
|
||||
public:
|
||||
Common::Array<RectEntry> _entries;
|
||||
public:
|
||||
RectResource(const byte *src, int size, bool isExtendedRects);
|
||||
RectResource(int xp, int yp, int width, int height);
|
||||
virtual ~RectResource() {}
|
||||
};
|
||||
|
||||
/* bvoy.blt resource types */
|
||||
|
||||
enum PictureFlag {
|
||||
PICFLAG_2 = 2, PICFLAG_PIC_OFFSET = 8, PICFLAG_CLEAR_SCREEN = 0x10,
|
||||
PICFLAG_20 = 0x20, PICFLAG_HFLIP = 0x40, PICFLAG_VFLIP = 0x80, PICFLAG_100 = 0x100,
|
||||
PICFLAG_CLEAR_SCREEN00 = 0x1000
|
||||
};
|
||||
|
||||
enum DisplayFlag {
|
||||
DISPFLAG_1 = 1, DISPFLAG_2 = 2, DISPFLAG_4 = 4, DISPFLAG_8 = 8,
|
||||
DISPFLAG_10 = 0x10, DISPFLAG_20 = 0x20, DISPFLAG_40 = 0x40, DISPFLAG_80 = 0x80,
|
||||
DISPFLAG_100 = 0x100, DISPFLAG_200 = 0x200, DISPFLAG_400 = 0x400,
|
||||
DISPFLAG_800 = 0x800, DISPFLAG_1000 = 0x1000, DISPFLAG_2000 = 0x2000,
|
||||
DISPFLAG_4000 = 0x4000, DISPFLAG_VIEWPORT = 0x8000, DISPFLAG_CURSOR = 0x10000,
|
||||
DISPFLAG_NONE = 0};
|
||||
|
||||
class DisplayResource {
|
||||
protected:
|
||||
VoyeurEngine *_vm;
|
||||
public:
|
||||
uint32 _flags;
|
||||
public:
|
||||
DisplayResource();
|
||||
DisplayResource(VoyeurEngine *vm);
|
||||
|
||||
/**
|
||||
* Fill a box of the given size at the current _drawPtr location
|
||||
*/
|
||||
void sFillBox(int width, int height);
|
||||
|
||||
/**
|
||||
* Draw text at the current pen position
|
||||
*/
|
||||
int drawText(const Common::String &msg);
|
||||
|
||||
/**
|
||||
* Return the width of a given text in the current font
|
||||
*/
|
||||
int textWidth(const Common::String &msg);
|
||||
|
||||
/**
|
||||
* Clip the given rectangle by the currently viewable area
|
||||
*/
|
||||
bool clipRect(Common::Rect &rect);
|
||||
};
|
||||
|
||||
class PictureResource: public DisplayResource {
|
||||
private:
|
||||
/**
|
||||
* Flip the image data horizontally
|
||||
*/
|
||||
void flipHorizontal(const byte *data);
|
||||
|
||||
/**
|
||||
* Flip the image data vertically
|
||||
*/
|
||||
void flipVertical(const byte *data);
|
||||
public:
|
||||
byte _select;
|
||||
byte _pick;
|
||||
byte _onOff;
|
||||
Common::Rect _bounds;
|
||||
uint32 _maskData;
|
||||
uint _planeSize;
|
||||
byte _keyColor;
|
||||
|
||||
/**
|
||||
* Image data for the picture
|
||||
*/
|
||||
byte *_imgData;
|
||||
|
||||
/**
|
||||
* Flag to indicate whether to free the image data
|
||||
*/
|
||||
DisposeAfterUse::Flag _freeImgData;
|
||||
public:
|
||||
PictureResource(BoltFilesState &state, const byte *src);
|
||||
PictureResource(int flags, int select, int pick, int onOff,
|
||||
const Common::Rect &bounds, int maskData, byte *imgData, int planeSize);
|
||||
PictureResource(Graphics::Surface *surface);
|
||||
PictureResource();
|
||||
virtual ~PictureResource();
|
||||
};
|
||||
|
||||
typedef void (ViewPortResource::*ViewPortMethodPtr)();
|
||||
|
||||
class ViewPortResource: public DisplayResource {
|
||||
private:
|
||||
BoltFilesState &_state;
|
||||
private:
|
||||
void setupViewPort(PictureResource *page, Common::Rect *clippingRect, ViewPortSetupPtr setupFn,
|
||||
ViewPortAddPtr addFn, ViewPortRestorePtr restoreFn);
|
||||
public:
|
||||
ViewPortResource *_parent;
|
||||
ViewPortSetupPtr _setupFn;
|
||||
int _pageCount;
|
||||
ViewPortAddPtr _addFn;
|
||||
int _pageIndex;
|
||||
ViewPortRestorePtr _restoreFn;
|
||||
int _lastPage;
|
||||
ScreenMethodPtr _fn1;
|
||||
Common::Rect _bounds;
|
||||
PictureResource *_currentPic;
|
||||
PictureResource *_activePage;
|
||||
PictureResource *_pages[2];
|
||||
|
||||
// Rect lists and counts. Note that _rectListCount values of '-1' seem to have
|
||||
// special significance, which is why I'm not making them redundant in favor
|
||||
// of the arrays' .size() method
|
||||
Common::Array<Common::Rect> *_rectListPtr[3];
|
||||
int _rectListCount[3];
|
||||
|
||||
Common::Rect _clipRect;
|
||||
Common::Rect _fontRect;
|
||||
public:
|
||||
ViewPortResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~ViewPortResource();
|
||||
|
||||
void setupViewPort();
|
||||
void setupViewPort(PictureResource *pic, Common::Rect *clippingRect = nullptr);
|
||||
void addSaveRect(int pageIndex, const Common::Rect &r);
|
||||
void fillPic(byte onOff);
|
||||
void drawIfaceTime();
|
||||
void drawPicPerm(PictureResource *pic, const Common::Point &pt);
|
||||
};
|
||||
|
||||
class ViewPortPalEntry {
|
||||
public:
|
||||
uint16 _rEntry, _gEntry, _bEntry;
|
||||
uint16 _rChange, _gChange, _bChange;
|
||||
uint16 _palIndex;
|
||||
public:
|
||||
ViewPortPalEntry(const byte *src);
|
||||
};
|
||||
|
||||
class ViewPortListResource {
|
||||
public:
|
||||
Common::Array<ViewPortPalEntry> _palette;
|
||||
Common::Array<ViewPortResource *> _entries;
|
||||
int _palIndex;
|
||||
|
||||
ViewPortListResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~ViewPortListResource() {}
|
||||
};
|
||||
|
||||
class FontResource {
|
||||
public:
|
||||
int _minChar, _maxChar;
|
||||
int _fontDepth;
|
||||
int _padding;
|
||||
int _fontHeight;
|
||||
int _topPadding;
|
||||
int *_charWidth;
|
||||
byte *_charOffsets;
|
||||
byte *_charImages;
|
||||
|
||||
FontResource(BoltFilesState &state, byte *src);
|
||||
virtual ~FontResource();
|
||||
};
|
||||
|
||||
enum FontJustify { ALIGN_LEFT = 0, ALIGN_CENTER = 1, ALIGN_RIGHT = 2 };
|
||||
|
||||
class FontInfoResource {
|
||||
public:
|
||||
FontResource *_curFont;
|
||||
byte _picFlags;
|
||||
byte _picSelect;
|
||||
byte _picPick;
|
||||
byte _picOnOff;
|
||||
byte _fontFlags;
|
||||
FontJustify _justify;
|
||||
int _fontSaveBack;
|
||||
Common::Point _pos;
|
||||
int _justifyWidth;
|
||||
int _justifyHeight;
|
||||
Common::Point _shadow;
|
||||
int _foreColor;
|
||||
int _backColor;
|
||||
int _shadowColor;
|
||||
public:
|
||||
FontInfoResource(BoltFilesState &state, const byte *src);
|
||||
FontInfoResource();
|
||||
FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, byte fontFlags,
|
||||
FontJustify justify, int fontSaveBack, const Common::Point &pos, int justifyWidth,
|
||||
int justifyHeight, const Common::Point &shadow, int foreColor, int backColor,
|
||||
int shadowColor);
|
||||
};
|
||||
|
||||
class CMapResource {
|
||||
private:
|
||||
VoyeurEngine *_vm;
|
||||
public:
|
||||
int _steps;
|
||||
int _fadeStatus;
|
||||
int _start;
|
||||
int _end;
|
||||
byte *_entries;
|
||||
public:
|
||||
CMapResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~CMapResource();
|
||||
|
||||
void startFade();
|
||||
};
|
||||
|
||||
class VInitCycleResource {
|
||||
private:
|
||||
BoltFilesState &_state;
|
||||
public:
|
||||
int _type[4];
|
||||
byte *_ptr[4];
|
||||
public:
|
||||
VInitCycleResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~VInitCycleResource() {}
|
||||
|
||||
void vStartCycle();
|
||||
void vStopCycle();
|
||||
};
|
||||
|
||||
/* stampblt.blt resources */
|
||||
|
||||
class PtrResource {
|
||||
public:
|
||||
Common::Array<BoltEntry *> _entries;
|
||||
|
||||
PtrResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~PtrResource() {}
|
||||
};
|
||||
|
||||
class ControlResource {
|
||||
public:
|
||||
int _memberIds[8];
|
||||
byte *_entries[8];
|
||||
int _stateId;
|
||||
StateResource *_state;
|
||||
|
||||
ControlResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~ControlResource() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores data about the intended victim
|
||||
*/
|
||||
class StateResource {
|
||||
public:
|
||||
int _vals[4];
|
||||
int &_victimIndex;
|
||||
int &_victimEvidenceIndex;
|
||||
int &_victimMurderIndex;
|
||||
|
||||
StateResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~StateResource() {}
|
||||
|
||||
/**
|
||||
* Synchronizes the game data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
class ThreadResource {
|
||||
public:
|
||||
static int _useCount[8];
|
||||
static void initUseCount();
|
||||
static void unloadAllStacks(VoyeurEngine *vm);
|
||||
|
||||
static void init();
|
||||
private:
|
||||
VoyeurEngine *_vm;
|
||||
Common::Point _aptPos;
|
||||
private:
|
||||
bool getStateInfo();
|
||||
byte *getDataOffset();
|
||||
void getButtonsText();
|
||||
void getButtonsFlags();
|
||||
void performOpenCard();
|
||||
const byte *getRecordOffset(const byte *p);
|
||||
const byte *getNextRecord(const byte *p);
|
||||
const byte *getSTAMPCard(int cardId);
|
||||
int getStateFromID(uint32 id);
|
||||
uint32 getSID(int sid);
|
||||
void cardAction(const byte *p);
|
||||
void doSTAMPCardAction();
|
||||
bool goToStateID(int stackId, int id);
|
||||
const byte *cardPerform(const byte *card);
|
||||
bool cardPerform2(const byte *p, int cardCmdId);
|
||||
void savePrevious();
|
||||
void setButtonFlag(int idx, byte bits);
|
||||
void clearButtonFlag(int idx, byte bits);
|
||||
|
||||
/**
|
||||
* Frees the apartment screen data
|
||||
*/
|
||||
void freeTheApt();
|
||||
|
||||
/**
|
||||
* Does any necessary animation at the start or end of showing the apartment.
|
||||
*/
|
||||
void doAptAnim(int mode);
|
||||
|
||||
/**
|
||||
* Updates the mansion scroll position if ncessary, and returns true if it
|
||||
* has been changed.
|
||||
*/
|
||||
bool checkMansionScroll();
|
||||
public:
|
||||
int _stateId;
|
||||
int _stackId;
|
||||
int _savedStateId;
|
||||
int _savedStackId;
|
||||
int _newStateId;
|
||||
int _newStackId;
|
||||
int _stateFlags;
|
||||
int _stateCount;
|
||||
int _parseCount;
|
||||
uint32 _nextStateId;
|
||||
byte *_threadInfoPtr;
|
||||
byte _buttonFlags[64];
|
||||
byte _buttonIds[64];
|
||||
byte *_ctlPtr;
|
||||
byte *_playCommandsPtr;
|
||||
|
||||
/**
|
||||
* Loads the specified stack
|
||||
*/
|
||||
bool loadAStack(int stackId);
|
||||
|
||||
/**
|
||||
* Unloads the specified stack
|
||||
*/
|
||||
void unloadAStack(int stackId);
|
||||
|
||||
/**
|
||||
* Initializes data for the thread based on the current state
|
||||
*/
|
||||
bool doState();
|
||||
|
||||
public:
|
||||
ThreadResource(BoltFilesState &state, const byte *src);
|
||||
virtual ~ThreadResource() {}
|
||||
|
||||
/**
|
||||
* Initialize the thread
|
||||
*/
|
||||
void initThreadStruct(int idx, int id);
|
||||
|
||||
/**
|
||||
* Go to a new state and/or stack
|
||||
*/
|
||||
bool goToState(int stackId, int stateId);
|
||||
|
||||
bool chooseSTAMPButton(int buttonId);
|
||||
|
||||
/**
|
||||
* Parses the script commands from the currently active stack
|
||||
*/
|
||||
void parsePlayCommands();
|
||||
|
||||
/**
|
||||
* Do the camera view looking at the mansion
|
||||
*/
|
||||
int doInterface();
|
||||
|
||||
/**
|
||||
* Do the display of a room that has one or more evidence hotspots
|
||||
* available for display
|
||||
*/
|
||||
void doRoom();
|
||||
|
||||
/**
|
||||
* Shows the apartment screen
|
||||
*/
|
||||
int doApt();
|
||||
|
||||
/**
|
||||
* Loads data needed for displaying the initial apartment screen
|
||||
*/
|
||||
void loadTheApt();
|
||||
|
||||
/**
|
||||
* Synchronizes the game data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif /* VOYEUR_FILES_H */
|
||||
1756
engines/voyeur/files_threads.cpp
Normal file
1756
engines/voyeur/files_threads.cpp
Normal file
File diff suppressed because it is too large
Load Diff
262
engines/voyeur/metaengine.cpp
Normal file
262
engines/voyeur/metaengine.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
/* 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 "voyeur/voyeur.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "voyeur/detection.h"
|
||||
|
||||
#define MAX_SAVES 99
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
{
|
||||
GAMEOPTION_COPY_PROTECTION,
|
||||
{
|
||||
// I18N: lockout is code to start the game
|
||||
_s("Enable lockout system"),
|
||||
_s("Require a lockout code to start the game."),
|
||||
"copy_protection",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
},
|
||||
},
|
||||
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
uint32 VoyeurEngine::getFeatures() const {
|
||||
return _gameDescription->desc.flags;
|
||||
}
|
||||
|
||||
Common::Language VoyeurEngine::getLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
Common::Platform VoyeurEngine::getPlatform() const {
|
||||
return _gameDescription->desc.platform;
|
||||
}
|
||||
|
||||
bool VoyeurEngine::getIsDemo() const {
|
||||
return _gameDescription->desc.flags & ADGF_DEMO;
|
||||
}
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
class VoyeurMetaEngine : public AdvancedMetaEngine<Voyeur::VoyeurGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "voyeur";
|
||||
}
|
||||
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
|
||||
return Voyeur::optionsList;
|
||||
}
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const Voyeur::VoyeurGameDescription *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 VoyeurMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSimpleSavesNames);
|
||||
}
|
||||
|
||||
bool Voyeur::VoyeurEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
Common::Error VoyeurMetaEngine::createInstance(OSystem *syst, Engine **engine, const Voyeur::VoyeurGameDescription *desc) const {
|
||||
*engine = new Voyeur::VoyeurEngine(syst,desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
SaveStateList VoyeurMetaEngine::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);
|
||||
|
||||
SaveStateList saveList;
|
||||
Voyeur::VoyeurSavegameHeader header;
|
||||
|
||||
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 (header.read(in)) {
|
||||
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 VoyeurMetaEngine::getMaximumSaveSlot() const {
|
||||
return MAX_SAVES;
|
||||
}
|
||||
|
||||
bool VoyeurMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String filename = Common::String::format("%s.%03d", target, slot);
|
||||
return g_system->getSavefileManager()->removeSavefile(filename);
|
||||
}
|
||||
|
||||
SaveStateDescriptor VoyeurMetaEngine::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) {
|
||||
Voyeur::VoyeurSavegameHeader header;
|
||||
header.read(f, false);
|
||||
delete f;
|
||||
|
||||
// Create the return descriptor
|
||||
SaveStateDescriptor desc(this, slot, header._saveName);
|
||||
desc.setThumbnail(header._thumbnail);
|
||||
desc.setSaveDate(header._saveYear, header._saveMonth, header._saveDay);
|
||||
desc.setSaveTime(header._saveHour, header._saveMinutes);
|
||||
desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
Common::KeymapArray VoyeurMetaEngine::initKeymaps(const char *target) const {
|
||||
|
||||
using namespace Common;
|
||||
using namespace Voyeur;
|
||||
|
||||
Keymap *engineKeymap = new Keymap(Keymap::kKeymapTypeGame, "voyeur-default", _("Default keymappings"));
|
||||
Keymap *cutsceneKeymap = new Keymap(Keymap::kKeymapTypeGame, "cutscene", _("Cutscene keymappings"));
|
||||
Keymap *roomKeymap = new Keymap(Keymap::kKeymapTypeGame, "room", _("Room keymappings"));
|
||||
Keymap *cameraKeymap = new Keymap(Keymap::kKeymapTypeGame, "camera", _("Camera keymappings"));
|
||||
Keymap *introKeymap = new Keymap(Keymap::kKeymapTypeGame, "intro", _("Intro keymappings"));
|
||||
|
||||
Common::Action *act;
|
||||
|
||||
act = new Common::Action(kStandardActionLeftClick, _("Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
engineKeymap->addAction(act);
|
||||
|
||||
act = new Common::Action(kStandardActionRightClick, _("Exit"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
engineKeymap->addAction(act);
|
||||
|
||||
act = new Common::Action(kStandardActionRightClick, _("Skip scene"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
cutsceneKeymap->addAction(act);
|
||||
|
||||
act = new Common::Action(kStandardActionLeftClick, _("View evidence"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
roomKeymap->addAction(act);
|
||||
|
||||
act = new Common::Action(kStandardActionRightClick, _("Exit / Put away evidence"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
roomKeymap->addAction(act);
|
||||
|
||||
act = new Common::Action(kStandardActionLeftClick, _("Enter room"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
cameraKeymap->addAction(act);
|
||||
|
||||
act = new Common::Action(kStandardActionRightClick, _("Exit"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
cameraKeymap->addAction(act);
|
||||
|
||||
act = new Common::Action("SKIP", _("Skip intro"));
|
||||
act->setCustomEngineActionEvent(kActionSkip);
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("SPACE");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
introKeymap->addAction(act);
|
||||
|
||||
KeymapArray keymaps(5);
|
||||
keymaps[0] = engineKeymap;
|
||||
keymaps[1] = cutsceneKeymap;
|
||||
keymaps[2] = roomKeymap;
|
||||
keymaps[3] = cameraKeymap;
|
||||
keymaps[4] = introKeymap;
|
||||
|
||||
cutsceneKeymap->setEnabled(false);
|
||||
roomKeymap->setEnabled(false);
|
||||
cameraKeymap->setEnabled(false);
|
||||
introKeymap->setEnabled(false);
|
||||
|
||||
return keymaps;
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(VOYEUR)
|
||||
REGISTER_PLUGIN_DYNAMIC(VOYEUR, PLUGIN_TYPE_ENGINE, VoyeurMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(VOYEUR, PLUGIN_TYPE_ENGINE, VoyeurMetaEngine);
|
||||
#endif
|
||||
26
engines/voyeur/module.mk
Normal file
26
engines/voyeur/module.mk
Normal file
@@ -0,0 +1,26 @@
|
||||
MODULE := engines/voyeur
|
||||
|
||||
MODULE_OBJS := \
|
||||
animation.o \
|
||||
data.o \
|
||||
debugger.o \
|
||||
events.o \
|
||||
files.o \
|
||||
files_threads.o \
|
||||
metaengine.o \
|
||||
screen.o \
|
||||
sound.o \
|
||||
staticres.o \
|
||||
voyeur.o \
|
||||
voyeur_game.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_VOYEUR), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
1076
engines/voyeur/screen.cpp
Normal file
1076
engines/voyeur/screen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
115
engines/voyeur/screen.h
Normal file
115
engines/voyeur/screen.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* 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 VOYEUR_GRAPHICS_H
|
||||
#define VOYEUR_GRAPHICS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/serializer.h"
|
||||
#include "graphics/screen.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
#define SCREEN_WIDTH 320
|
||||
#define SCREEN_HEIGHT 200
|
||||
|
||||
class VoyeurEngine;
|
||||
class Screen;
|
||||
class DisplayResource;
|
||||
class PictureResource;
|
||||
class ViewPortResource;
|
||||
class ViewPortListResource;
|
||||
class FontResource;
|
||||
class FontInfoResource;
|
||||
class CMapResource;
|
||||
|
||||
class DrawInfo {
|
||||
public:
|
||||
int _penColor;
|
||||
Common::Point _pos;
|
||||
public:
|
||||
DrawInfo(int penColor, const Common::Point &pos);
|
||||
};
|
||||
|
||||
typedef void (Screen::*ScreenMethodPtr)();
|
||||
typedef void (Screen::*ViewPortSetupPtr)(ViewPortResource *);
|
||||
typedef void (Screen::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds);
|
||||
typedef void (Screen::*ViewPortRestorePtr)(ViewPortResource *);
|
||||
|
||||
class Screen: public Graphics::Screen {
|
||||
public:
|
||||
byte _VGAColors[Graphics::PALETTE_SIZE];
|
||||
PictureResource *_backgroundPage;
|
||||
int _SVGAMode;
|
||||
ViewPortListResource *_viewPortListPtr;
|
||||
ViewPortResource *_vPort;
|
||||
bool _saveBack;
|
||||
Common::Rect *_clipPtr;
|
||||
uint _planeSelect;
|
||||
CMapResource *_backColors;
|
||||
FontInfoResource *_fontPtr;
|
||||
PictureResource *_fontChar;
|
||||
DrawInfo *_drawPtr;
|
||||
DrawInfo _defaultDrawInfo;
|
||||
private:
|
||||
VoyeurEngine *_vm;
|
||||
|
||||
void restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
|
||||
PictureResource *srcPic, PictureResource *destPic);
|
||||
public:
|
||||
Screen(VoyeurEngine *vm);
|
||||
~Screen() override;
|
||||
|
||||
void sInitGraphics();
|
||||
|
||||
void setupMCGASaveRect(ViewPortResource *viewPort);
|
||||
void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
|
||||
void restoreMCGASaveRect(ViewPortResource *viewPort);
|
||||
void addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
|
||||
|
||||
void sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay, const Common::Point &initialOffset);
|
||||
void fillPic(DisplayResource *display, byte onOff);
|
||||
void sDisplayPic(PictureResource *pic);
|
||||
void drawANumber(DisplayResource *display, int num, const Common::Point &pt);
|
||||
void flipPage();
|
||||
void setPalette(const byte *palette, int start, int count);
|
||||
void setPalette128(const byte *palette, int start, int count);
|
||||
void resetPalette();
|
||||
void setColor(int idx, byte r, byte g, byte b);
|
||||
void setOneColor(int idx, byte r, byte g, byte b);
|
||||
void setColors(int start, int count, const byte *pal);
|
||||
void screenReset();
|
||||
void fadeDownICF1(int steps);
|
||||
void fadeUpICF1(int steps = 0);
|
||||
void fadeDownICF(int steps);
|
||||
void drawDot();
|
||||
|
||||
/**
|
||||
* Synchronizes the game data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif /* VOYEUR_GRAPHICS_H */
|
||||
87
engines/voyeur/sound.cpp
Normal file
87
engines/voyeur/sound.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 "audio/audiostream.h"
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "audio/decoders/voc.h"
|
||||
#include "common/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "voyeur/sound.h"
|
||||
#include "voyeur/staticres.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
SoundManager::SoundManager(Audio::Mixer *mixer) {
|
||||
_mixer = mixer;
|
||||
_vocOffset = 0;
|
||||
}
|
||||
|
||||
void SoundManager::playVOCMap(byte *voc, int vocSize) {
|
||||
Common::MemoryReadStream *dataStream = new Common::MemoryReadStream(voc, vocSize, DisposeAfterUse::NO);
|
||||
Audio::AudioStream *audioStream = Audio::makeVOCStream(dataStream, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
|
||||
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream);
|
||||
}
|
||||
|
||||
void SoundManager::abortVOCMap() {
|
||||
_mixer->stopHandle(_soundHandle);
|
||||
}
|
||||
|
||||
void SoundManager::stopVOCPlay() {
|
||||
_mixer->stopHandle(_soundHandle);
|
||||
_vocOffset = 0;
|
||||
}
|
||||
|
||||
void SoundManager::setVOCOffset(int offset) {
|
||||
_vocOffset = offset;
|
||||
}
|
||||
|
||||
Common::Path SoundManager::getVOCFileName(int idx) {
|
||||
assert(idx >= 0);
|
||||
return Common::Path(Common::String::format("%s.voc", SZ_FILENAMES[idx]));
|
||||
}
|
||||
|
||||
void SoundManager::startVOCPlay(const Common::Path &filename) {
|
||||
Common::File f;
|
||||
if (!f.open(filename))
|
||||
error("Could not find voc file - %s", filename.toString().c_str());
|
||||
|
||||
Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()),
|
||||
Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
|
||||
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream);
|
||||
audioStream->seek(Audio::Timestamp(_vocOffset * 1000, 11025));
|
||||
}
|
||||
|
||||
void SoundManager::startVOCPlay(int soundId) {
|
||||
startVOCPlay(getVOCFileName(soundId));
|
||||
}
|
||||
|
||||
int SoundManager::getVOCStatus() {
|
||||
return _mixer->isSoundHandleActive(_soundHandle);
|
||||
}
|
||||
|
||||
uint32 SoundManager::getVOCFrame() {
|
||||
Audio::Timestamp timestamp = _mixer->getElapsedTime(_soundHandle);
|
||||
return timestamp.secs();
|
||||
}
|
||||
|
||||
} // End of namespace Voyeur
|
||||
52
engines/voyeur/sound.h
Normal file
52
engines/voyeur/sound.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 VOYEUR_SOUND_H
|
||||
#define VOYEUR_SOUND_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/path.h"
|
||||
#include "audio/mixer.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
class SoundManager {
|
||||
private:
|
||||
Audio::Mixer *_mixer;
|
||||
Audio::SoundHandle _soundHandle;
|
||||
int _vocOffset;
|
||||
public:
|
||||
SoundManager(Audio::Mixer *mixer);
|
||||
|
||||
void playVOCMap(byte *voc, int vocSize);
|
||||
void stopVOCPlay();
|
||||
void abortVOCMap();
|
||||
void setVOCOffset(int offset);
|
||||
Common::Path getVOCFileName(int idx);
|
||||
void startVOCPlay(const Common::Path &filename);
|
||||
void startVOCPlay(int soundId);
|
||||
int getVOCStatus();
|
||||
uint32 getVOCFrame();
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif /* VOYEUR_SOUND_H */
|
||||
165
engines/voyeur/staticres.cpp
Normal file
165
engines/voyeur/staticres.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "voyeur/staticres.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
const int COMPUTER_DEFAULTS[] = {
|
||||
18, 1, 0, 1, 33, 0, 998, -1, 18, 2, 0, 1, 41, 0,
|
||||
998, -1, 18, 3, 0, 1, 47, 0, 998, -1, 18, 4, 0,
|
||||
1, 53, 0, 998, -1, 18, 5, 0, 1, 46, 0, 998, -1,
|
||||
18, 6, 0, 1, 50, 0, 998, -1, 18, 7, 0, 1, 40, 0,
|
||||
998, -1, 18, 8, 0, 1, 43, 0, 998, -1, 19, 1, 0,
|
||||
2, 28, 0, 998, -1
|
||||
};
|
||||
|
||||
const int RESOLVE_TABLE[] = {
|
||||
0x2A00, 0x4A00, 0x1000, 0x4B00, 0x2C00, 0x4F00, 0x1400, 0x5000,
|
||||
0x1700, 0x5100, 0x1800, 0x5200, 0x3300, 0x5400, 0x3700, 0x5500,
|
||||
0x1A00, 0x1C00, 0x1E00, 0x1F00, 0x2100, 0x2200, 0x2400, 0x2700,
|
||||
0x2B00, 0x1100, 0x4C00, 0x1200, 0x4D00, 0x1300, 0x4E00, 0x2E00,
|
||||
0x1900, 0x3200, 0x3400, 0x3800, 0x2800, 0x3E00, 0x4100, 0x2900,
|
||||
0x4400, 0x4600, 0x5300, 0x3900, 0x7600, 0x7200, 0x7300, 0x7400,
|
||||
0x7500
|
||||
};
|
||||
|
||||
const int LEVEL_H[] = {
|
||||
4, 7, 7, 8, 9, 10, 2, 2, 4, 8, 8, 9, 9, 10, 10, 11, 11
|
||||
};
|
||||
|
||||
const int LEVEL_M[] = {
|
||||
0, 0, 30, 0, 30, 0, 0, 0, 30, 0, 30, 0, 45, 0, 30, 0, 30
|
||||
};
|
||||
|
||||
const int BLIND_TABLE[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 9, 10, 11, 1, 11, 5, 12,
|
||||
13, 16, 15, 16, 17, 18, 5, 6, 18, 17, 13, 13, 14, 14,
|
||||
5, 12, 6, 6, 13, 14, 13
|
||||
};
|
||||
|
||||
const int COMPUTER_SCREEN_TABLE[] = {
|
||||
269, 128, 307, 163,
|
||||
269, 128, 307, 163,
|
||||
68, 79, 98, 102,
|
||||
68, 79, 98, 102,
|
||||
68, 79, 98, 102,
|
||||
68, 79, 98, 102,
|
||||
248, 138, 291, 163,
|
||||
83, 132, 143, 156,
|
||||
248, 138, 291, 163,
|
||||
83, 132, 143, 156,
|
||||
83, 132, 143, 156,
|
||||
248, 138, 291, 163,
|
||||
68, 79, 98, 102,
|
||||
68, 79, 98, 102
|
||||
};
|
||||
|
||||
const char *const SZ_FILENAMES[] = {
|
||||
"A2110100", nullptr, "A2300100", nullptr, "B1220100", nullptr, "C1220100", nullptr,
|
||||
"C1290100", nullptr, "D1220100", nullptr, "D1270100", nullptr, "E1210100", nullptr,
|
||||
"E1260100", nullptr, "E1280100", nullptr, "E1325100", nullptr, "F1200100", nullptr,
|
||||
"G1250100", nullptr, "G1260100", nullptr, "H1200100", nullptr, "H1230100", nullptr,
|
||||
"H1310100", nullptr, "I1300100", nullptr, "J1220100", nullptr, "J1230100", nullptr,
|
||||
"J1320100", nullptr, "K1260100", nullptr, "K1280100", nullptr, "K1325100", nullptr,
|
||||
"L1210100", nullptr, "L1280100", nullptr, "L1290100", nullptr, "L1300100", nullptr,
|
||||
"L1310100", nullptr, "M1260100", nullptr, "M1310100", nullptr, "N1210100", nullptr,
|
||||
"N1225100", nullptr, "N1275510", nullptr, "N1280510", nullptr, "N1325100", nullptr,
|
||||
"O1230100", nullptr, "O1260100", nullptr, "O1260520", nullptr, "O1280100", nullptr,
|
||||
"O1325540", nullptr, "P1276710", nullptr, "P1280540", nullptr, "P1280740", nullptr,
|
||||
"P1290510", nullptr, "P1325100", nullptr, "P1325300", nullptr, "P1325520", nullptr,
|
||||
"Q1230100", nullptr, "Q1240530", nullptr, "Q1240730", nullptr, "Q1260100", nullptr,
|
||||
"Q1260520", nullptr, "Q1260720", nullptr, "Q1325100", nullptr, "R1280540", nullptr,
|
||||
"Z1110510", nullptr, "Z1110520", nullptr, "Z1110530", nullptr, "Z1110540", nullptr,
|
||||
"Z1110545", nullptr, "Z2320100", nullptr, "Z2905300", nullptr, "Z3110100", nullptr,
|
||||
"Z3115510", nullptr, "Z3115520", nullptr, "Z3115530", nullptr, "Z3115540", nullptr,
|
||||
"Z4915100", nullptr, "Z4915200", nullptr, "Z4915300",
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
"MMARG", "MZACK", "MREED", "MJESSI", "MCHLOE", "MCAMERA", "MENDCRED",
|
||||
"NEWCALL2", "PHONE1", "PHONE2", "PHONE3", "PHONE6", "PHONE8",
|
||||
"B1300100", "C1250100", "C1320100", "D1320100", "E1210200", "E1260200",
|
||||
"E1280200", "E1310100", "G1230100", "G1300100", "I1210100", "I1270100",
|
||||
"I1280100", "J1250100", "J1280100", "K1260200", "K1270100", "K1325200",
|
||||
"L1240100", "M1200100", "M1230100", "M1290100", "N1250100", "N1260100",
|
||||
"N1280100", "O1250510", "O1290510", "O1320510", "O1320710", "P1240100",
|
||||
"P1240530", "P1260100", "P1270100", "P1280100", "P1280530", "P1320530",
|
||||
"Q1240100", "E1325100"
|
||||
};
|
||||
|
||||
const char *const SATURDAY_EN = "Saturday";
|
||||
const char *const SUNDAY_EN = "Sunday";
|
||||
const char *const MONDAY_EN = "Monday Morning";
|
||||
const char *const AM_EN = "am";
|
||||
const char *const PM_EN = "pm";
|
||||
const char *const START_OF_MESSAGE_EN = "*** Start of Message ***";
|
||||
const char *const END_OF_MESSAGE_EN = "*** End of Message ***";
|
||||
const char *const EVENT_TYPE_STRINGS_EN[4] = { "Video", "Audio", "Evidence", "Computer" };
|
||||
const char *const SATURDAY_AFTERNOON_EN = "Saturday Afternoon";
|
||||
const char *const PLAYER_APARTMENT_EN = "Player's Apartment";
|
||||
|
||||
const char *const SATURDAY_DE = "Samstag";
|
||||
const char *const SUNDAY_DE = "Sonntag";
|
||||
const char *const MONDAY_DE = "Montag Morgen";
|
||||
const char *const AM_DE = " Uhr";
|
||||
const char *const PM_DE = " Uhr";
|
||||
const char *const START_OF_MESSAGE_DE = " *** TEXTANFANG *** ";
|
||||
const char *const END_OF_MESSAGE_DE = " *** TEXTENDE *** ";
|
||||
const char *const EVENT_TYPE_STRINGS_DE[4] = {"Video", "Audio", "Beweis", "Computer"};
|
||||
const char *const SATURDAY_AFTERNOON_DE = "Samstag Nachmittag";
|
||||
const char *const PLAYER_APARTMENT_DE = "Wohnung des Spielers";
|
||||
|
||||
int DOT_LINE_START[9] = {
|
||||
0xE880, 0xE9C0, 0xEB00, 0xEC40, 0xED80, 0xEEC0, 0xF000, 0xF140, 0xF280
|
||||
};
|
||||
int DOT_LINE_OFFSET[9] = {
|
||||
144, 143, 142, 141, 141, 141, 142, 143, 144
|
||||
};
|
||||
int DOT_LINE_LENGTH[9] = {
|
||||
5, 7, 9, 11, 11, 11, 9, 7, 5
|
||||
};
|
||||
|
||||
const char *const PIRACY_MESSAGE_EN[] = {
|
||||
"It is illegal to make",
|
||||
"unauthorized copies of",
|
||||
"this software. Duplication",
|
||||
"of this software for any",
|
||||
"reason including sale,",
|
||||
"loan, rental, or gift is a",
|
||||
"crime. Penalties include",
|
||||
"fines of up to $50,000",
|
||||
"and jail terms up to",
|
||||
"5 years."
|
||||
};
|
||||
|
||||
const char *const PIRACY_MESSAGE_DE[] = {
|
||||
"VOYEUR",
|
||||
"A POV Entert. Group Production",
|
||||
"Copyright 1993, 1994",
|
||||
"Philips Interactive Media",
|
||||
"Alle Urheberrechte und",
|
||||
"Leistungsschutzrechte",
|
||||
"vorbehalten. Kein Verleih.",
|
||||
"Keine unerlaubte Vervielfaeltigung,",
|
||||
"Vermietung, Auffuehrung",
|
||||
"oder Sendung."
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
74
engines/voyeur/staticres.h
Normal file
74
engines/voyeur/staticres.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VOYEUR_STATICRES_H
|
||||
#define VOYEUR_STATICRES_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Voyeur {
|
||||
|
||||
extern const int COMPUTER_DEFAULTS[];
|
||||
|
||||
extern const int RESOLVE_TABLE[];
|
||||
|
||||
extern const int LEVEL_H[];
|
||||
|
||||
extern const int LEVEL_M[];
|
||||
|
||||
extern const int BLIND_TABLE[];
|
||||
|
||||
extern const int COMPUTER_SCREEN_TABLE[];
|
||||
|
||||
extern const char *const SZ_FILENAMES[];
|
||||
|
||||
extern const char *const SATURDAY_EN;
|
||||
extern const char *const SUNDAY_EN;
|
||||
extern const char *const MONDAY_EN;
|
||||
extern const char *const AM_EN;
|
||||
extern const char *const PM_EN;
|
||||
extern const char *const START_OF_MESSAGE_EN;
|
||||
extern const char *const END_OF_MESSAGE_EN;
|
||||
extern const char *const EVENT_TYPE_STRINGS_EN[4];
|
||||
extern const char *const SATURDAY_AFTERNOON_EN;
|
||||
extern const char *const PLAYER_APARTMENT_EN;
|
||||
|
||||
extern const char *const SATURDAY_DE;
|
||||
extern const char *const SUNDAY_DE;
|
||||
extern const char *const MONDAY_DE;
|
||||
extern const char *const AM_DE;
|
||||
extern const char *const PM_DE;
|
||||
extern const char *const START_OF_MESSAGE_DE;
|
||||
extern const char *const END_OF_MESSAGE_DE;
|
||||
extern const char *const EVENT_TYPE_STRINGS_DE[4];
|
||||
extern const char *const SATURDAY_AFTERNOON_DE;
|
||||
extern const char *const PLAYER_APARTMENT_DE;
|
||||
|
||||
extern int DOT_LINE_START[9];
|
||||
extern int DOT_LINE_OFFSET[9];
|
||||
extern int DOT_LINE_LENGTH[9];
|
||||
|
||||
extern const char *const PIRACY_MESSAGE_EN[];
|
||||
extern const char *const PIRACY_MESSAGE_DE[];
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif
|
||||
1014
engines/voyeur/voyeur.cpp
Normal file
1014
engines/voyeur/voyeur.cpp
Normal file
File diff suppressed because it is too large
Load Diff
326
engines/voyeur/voyeur.h
Normal file
326
engines/voyeur/voyeur.h
Normal file
@@ -0,0 +1,326 @@
|
||||
/* 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 VOYEUR_VOYEUR_H
|
||||
#define VOYEUR_VOYEUR_H
|
||||
|
||||
#include "voyeur/debugger.h"
|
||||
#include "voyeur/data.h"
|
||||
#include "voyeur/events.h"
|
||||
#include "voyeur/files.h"
|
||||
#include "voyeur/screen.h"
|
||||
#include "voyeur/sound.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "common/error.h"
|
||||
#include "common/random.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/util.h"
|
||||
#include "engines/engine.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
/**
|
||||
* This is the namespace of the Voyeur engine.
|
||||
*
|
||||
* Status of this engine: Complete
|
||||
*
|
||||
* Games using this engine:
|
||||
* - Voyeur (Dos)
|
||||
*/
|
||||
namespace Voyeur {
|
||||
|
||||
#define DEBUG_BASIC 1
|
||||
#define DEBUG_INTERMEDIATE 2
|
||||
#define DEBUG_DETAILED 3
|
||||
|
||||
// Constants used for doInterface display of the mansion
|
||||
#define MANSION_MAX_X 784
|
||||
#define MANSION_MAX_Y 150
|
||||
#define MANSION_VIEW_X 40
|
||||
#define MANSION_VIEW_Y 27
|
||||
#define MANSION_VIEW_WIDTH 240
|
||||
#define MANSION_VIEW_HEIGHT 148
|
||||
#define MANSION_SCROLL_AREA_X 20
|
||||
#define MANSION_SCROLL_AREA_Y 20
|
||||
#define MANSION_SCROLL_INC_X 4
|
||||
#define MANSION_SCROLL_INC_Y 4
|
||||
|
||||
enum VoyeurDebugChannels {
|
||||
kDebugScripts = 1,
|
||||
};
|
||||
|
||||
enum VoyeurArea { AREA_NONE, AREA_APARTMENT, AREA_INTERFACE, AREA_ROOM, AREA_EVIDENCE };
|
||||
|
||||
struct VoyeurGameDescription;
|
||||
|
||||
enum VOYEURAction {
|
||||
kActionNone,
|
||||
kActionSkip,
|
||||
};
|
||||
|
||||
class VoyeurEngine : public Engine {
|
||||
private:
|
||||
const VoyeurGameDescription *_gameDescription;
|
||||
Common::RandomSource _randomSource;
|
||||
FontInfoResource _defaultFontInfo;
|
||||
|
||||
void ESP_Init();
|
||||
void globalInitBolt();
|
||||
void initBolt();
|
||||
void vInitInterrupts();
|
||||
void initInput();
|
||||
|
||||
bool doHeadTitle();
|
||||
void showConversionScreen();
|
||||
bool doLock();
|
||||
void showTitleScreen();
|
||||
void doOpening();
|
||||
|
||||
void playStamp();
|
||||
void initStamp();
|
||||
void closeStamp();
|
||||
|
||||
void showLogo8Intro();
|
||||
|
||||
/**
|
||||
* Shows the game ending title animation
|
||||
*/
|
||||
void doTailTitle();
|
||||
|
||||
/**
|
||||
* Shows the game ending credits
|
||||
*/
|
||||
void doClosingCredits();
|
||||
|
||||
/**
|
||||
* Shows the final anti-piracy message before exiting the game
|
||||
*/
|
||||
void doPiracy();
|
||||
|
||||
/**
|
||||
* Review previous tape recordings on the TV
|
||||
*/
|
||||
void reviewTape();
|
||||
|
||||
/**
|
||||
* Shows the TV gossip animation
|
||||
*/
|
||||
void doGossip();
|
||||
|
||||
/**
|
||||
* Shows the animation of the VCR tape during the 'Call the Police' sequence
|
||||
*/
|
||||
void doTapePlaying();
|
||||
|
||||
/**
|
||||
* Does a check as to whether a murder has been witnessed
|
||||
*/
|
||||
bool checkForMurder();
|
||||
|
||||
/**
|
||||
* Does a check for whether incriminating evidence has been revealed
|
||||
*/
|
||||
bool checkForIncriminate();
|
||||
|
||||
/**
|
||||
* Plays a video event previously witnessed
|
||||
*/
|
||||
void playAVideoEvent(int eventIndex);
|
||||
|
||||
/**
|
||||
* Shows the user a screen to select one of four characters to send the
|
||||
* video tape to
|
||||
*/
|
||||
int getChooseButton();
|
||||
|
||||
/**
|
||||
* Synchronizes the game data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Resets the mansion view position
|
||||
*/
|
||||
void centerMansionView();
|
||||
protected:
|
||||
// Engine APIs
|
||||
Common::Error run() override;
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
public:
|
||||
BoltFile *_bVoy;
|
||||
Debugger *_debugger;
|
||||
EventsManager *_eventsManager;
|
||||
FilesManager *_filesManager;
|
||||
Screen *_screen;
|
||||
SoundManager *_soundManager;
|
||||
SVoy *_voy;
|
||||
|
||||
BoltFile *_stampLibPtr;
|
||||
BoltGroup *_controlGroupPtr;
|
||||
ControlResource *_controlPtr;
|
||||
byte *_stampData;
|
||||
BoltGroup *_stackGroupPtr;
|
||||
int _glGoState;
|
||||
int _glGoStack;
|
||||
int _stampFlags;
|
||||
int _playStampGroupId;
|
||||
int _currentVocId;
|
||||
|
||||
int _audioVideoId;
|
||||
const int *_resolvePtr;
|
||||
int _iForceDeath;
|
||||
int _checkTransitionId;
|
||||
int _gameHour;
|
||||
int _gameMinute;
|
||||
int _flashTimeVal;
|
||||
bool _flashTimeFlag;
|
||||
int _timeBarVal;
|
||||
int _checkPhoneVal;
|
||||
Common::Point _mansionViewPos;
|
||||
ThreadResource *_mainThread;
|
||||
VoyeurArea _voyeurArea;
|
||||
int _loadGameSlot;
|
||||
public:
|
||||
VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc);
|
||||
~VoyeurEngine() override;
|
||||
void GUIError(const Common::String &msg);
|
||||
|
||||
uint32 getFeatures() const;
|
||||
Common::Language getLanguage() const;
|
||||
Common::Platform getPlatform() const;
|
||||
uint16 getVersion() const;
|
||||
bool getIsDemo() 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;
|
||||
void loadGame(int slot);
|
||||
|
||||
void playRL2Video(const Common::Path &filename);
|
||||
void doTransitionCard(const Common::String &time, const Common::String &location);
|
||||
|
||||
/**
|
||||
* Play a given video
|
||||
*/
|
||||
void playAVideo(int videoId);
|
||||
|
||||
/**
|
||||
* Play a given video for a given amount of time. This is particularly used
|
||||
* for later tape playback, where it will only play back as much of the video
|
||||
* as the user originally watched (since they can break out of watching a video).
|
||||
*/
|
||||
void playAVideoDuration(int videoId, int duration);
|
||||
|
||||
/**
|
||||
* Play an audio sequence
|
||||
*/
|
||||
void playAudio(int audioId);
|
||||
|
||||
void makeViewFinder();
|
||||
void makeViewFinderP();
|
||||
void initIFace();
|
||||
void checkTransition();
|
||||
int doComputerText(int maxLen);
|
||||
void getComputerBrush();
|
||||
|
||||
/**
|
||||
* Displays the time/charge remaining on the video camera screen
|
||||
*/
|
||||
void doTimeBar();
|
||||
|
||||
/**
|
||||
* If necessary, flashes the time remaining bar on the video camera screen
|
||||
*/
|
||||
void flashTimeBar();
|
||||
|
||||
/**
|
||||
* Handle scrolling of the mansion view in the camera sights
|
||||
*/
|
||||
void doScroll(const Common::Point &pt);
|
||||
|
||||
/**
|
||||
* Check for phone call
|
||||
*/
|
||||
void checkPhoneCall();
|
||||
|
||||
/**
|
||||
* Display evidence sequence from within a room
|
||||
* Suspension of disbelief needed to believe that recording from a distance,
|
||||
* you could still flip through the often pages of evidence for a single hotspot.
|
||||
*/
|
||||
void doEvidDisplay(int evidId, int eventId);
|
||||
|
||||
/**
|
||||
* Flips the active page and waits until it's drawn
|
||||
*/
|
||||
void flipPageAndWait();
|
||||
|
||||
/**
|
||||
* Flips the active page and waits until it's drawn and faded in
|
||||
*/
|
||||
void flipPageAndWaitForFade();
|
||||
|
||||
/**
|
||||
* Returns the string for the current in-game day of the week
|
||||
*/
|
||||
Common::String getDayName();
|
||||
|
||||
/**
|
||||
* Returns the string for the current in-game time of day
|
||||
*/
|
||||
Common::String getTimeOfDay();
|
||||
|
||||
/**
|
||||
* Show the ending sequence of the arrest
|
||||
*/
|
||||
void showEndingNews();
|
||||
};
|
||||
|
||||
#define VOYEUR_SAVEGAME_VERSION 3
|
||||
|
||||
/**
|
||||
* Header for Voyeur savegame files
|
||||
*/
|
||||
struct VoyeurSavegameHeader {
|
||||
uint8 _version;
|
||||
Common::String _saveName;
|
||||
Graphics::Surface *_thumbnail;
|
||||
int _saveYear, _saveMonth, _saveDay;
|
||||
int _saveHour, _saveMinutes;
|
||||
int _totalFrames;
|
||||
|
||||
/**
|
||||
* Read in the header from the specified file
|
||||
*/
|
||||
bool read(Common::InSaveFile *f, bool skipThumbnail = true);
|
||||
|
||||
/**
|
||||
* Write out header information to the specified file
|
||||
*/
|
||||
void write(Common::OutSaveFile *f, VoyeurEngine *vm, const Common::String &saveName);
|
||||
};
|
||||
|
||||
} // End of namespace Voyeur
|
||||
|
||||
#endif /* VOYEUR_VOYEUR_H */
|
||||
1439
engines/voyeur/voyeur_game.cpp
Normal file
1439
engines/voyeur/voyeur_game.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user