PRINCE: midi music player added. mob and object lists added
This commit is contained in:
parent
5357724657
commit
84784add68
16 changed files with 864 additions and 53 deletions
|
@ -31,6 +31,8 @@ Debugger::Debugger(PrinceEngine *vm) : GUI::Debugger(), _vm(vm) {
|
|||
DCmd_Register("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag));
|
||||
DCmd_Register("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag));
|
||||
DCmd_Register("viewflc", WRAP_METHOD(Debugger, Cmd_ViewFlc));
|
||||
DCmd_Register("initroom", WRAP_METHOD(Debugger, Cmd_InitRoom));
|
||||
DCmd_Register("changecursor", WRAP_METHOD(Debugger, Cmd_ChangeCursor));
|
||||
}
|
||||
|
||||
static int strToInt(const char *s) {
|
||||
|
@ -108,4 +110,29 @@ bool Debugger::Cmd_ViewFlc(int argc, const char **argv) {
|
|||
_vm->loadAnim(flagNum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_InitRoom(int argc, const char **argv) {
|
||||
// Check for a flag to clear
|
||||
if (argc != 2) {
|
||||
DebugPrintf("Usage: %s <anim number>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int flagNum = strToInt(argv[1]);
|
||||
_vm->loadLocation(flagNum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_ChangeCursor(int argc, const char **argv) {
|
||||
// Check for a flag to clear
|
||||
if (argc != 2) {
|
||||
DebugPrintf("Usage: %s <curId>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int flagNum = strToInt(argv[1]);
|
||||
_vm->changeCursor(flagNum);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ private:
|
|||
bool Cmd_GetFlag(int argc, const char **argv);
|
||||
bool Cmd_ClearFlag(int argc, const char **argv);
|
||||
bool Cmd_ViewFlc(int argc, const char **argv);
|
||||
bool Cmd_InitRoom(int argc, const char **argv);
|
||||
bool Cmd_ChangeCursor(int argc, const char **argv);
|
||||
|
||||
PrinceEngine *_vm;
|
||||
};
|
||||
|
|
|
@ -46,7 +46,6 @@ bool Font::load(Common::SeekableReadStream &stream) {
|
|||
}
|
||||
|
||||
int Font::getFontHeight() const {
|
||||
debug("Font::getFontHeight %d", _fontData[5]);
|
||||
return _fontData[5];
|
||||
}
|
||||
|
||||
|
@ -70,15 +69,20 @@ int Font::getCharWidth(byte chr) const {
|
|||
return getChrData(chr)._width;
|
||||
}
|
||||
|
||||
void Font::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const {
|
||||
void Font::drawChar(Graphics::Surface *dst, byte chr, int posX, int posY, uint32 color) const {
|
||||
const ChrData chrData = getChrData(chr);
|
||||
const byte *src = chrData._pixels;
|
||||
byte *target = (byte *)dst->getBasePtr(x, y);
|
||||
|
||||
for (int i = 0; i < chrData._height; i++) {
|
||||
memcpy(target, src, chrData._width);
|
||||
src += chrData._width;
|
||||
target += dst->pitch;
|
||||
for (int y = 0; y < chrData._height; ++y) {
|
||||
for (int x = 0; x < chrData._width; ++x) {
|
||||
byte d = chrData._pixels[x + (chrData._width * y)];
|
||||
if (d == 0) d = 255;
|
||||
else if (d == 1) d = 0;
|
||||
else if (d == 2) d = color;
|
||||
else if (d == 3) d = 0;
|
||||
if (d != 255) {
|
||||
*(byte*)dst->getBasePtr(posX + x, posY + y) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ void GraphicsMan::update() {
|
|||
_vm->_system->copyRectToScreen((byte*)_frontScreen->getBasePtr(0,0), 640, 0, 0, 640, 480);
|
||||
|
||||
_vm->_system->updateScreen();
|
||||
_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,15 +54,19 @@ void GraphicsMan::change() {
|
|||
|
||||
void GraphicsMan::draw(const Graphics::Surface *s)
|
||||
{
|
||||
for (uint y = 0; y < 480; y++)
|
||||
memcpy((byte*)_frontScreen->getBasePtr(0, y), (byte*)s->getBasePtr(0, y), 640);
|
||||
change();
|
||||
uint16 w = MIN(_frontScreen->w, s->w);
|
||||
for (uint y = 0; y < s->h; y++) {
|
||||
if (y < _frontScreen->h) {
|
||||
memcpy((byte*)_frontScreen->getBasePtr(0, y), (byte*)s->getBasePtr(0, y), w);
|
||||
}
|
||||
}
|
||||
change();
|
||||
}
|
||||
|
||||
void GraphicsMan::drawTransparent(const Graphics::Surface *s)
|
||||
{
|
||||
for (uint y = 0; y < 480; ++y) {
|
||||
for (uint x = 0; x < 640; ++x) {
|
||||
for (uint y = 0; y < s->h; ++y) {
|
||||
for (uint x = 0; x < s->w; ++x) {
|
||||
byte pixel = *((byte*)s->getBasePtr(x,y));
|
||||
if (pixel != 255) {
|
||||
*((byte*)_frontScreen->getBasePtr(x, y)) = pixel;
|
||||
|
|
|
@ -53,7 +53,6 @@ private:
|
|||
PrinceEngine *_vm;
|
||||
|
||||
bool _changed;
|
||||
byte _palette[3 * 256];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
|
||||
namespace Prince {
|
||||
|
||||
class MhwanhDecoder : public Graphics::ImageDecoder
|
||||
{
|
||||
class MhwanhDecoder : public Graphics::ImageDecoder {
|
||||
public:
|
||||
MhwanhDecoder();
|
||||
virtual ~MhwanhDecoder();
|
||||
|
|
63
engines/prince/mob.cpp
Normal file
63
engines/prince/mob.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/mob.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
bool Mob::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
int32 pos = stream.pos();
|
||||
|
||||
uint16 visible = stream.readUint16LE();
|
||||
|
||||
if (visible == 0xFFFF)
|
||||
return false;
|
||||
|
||||
_visible = visible;
|
||||
_type = stream.readUint16LE();
|
||||
_rect.left = stream.readUint16LE();
|
||||
_rect.top = stream.readUint16LE();
|
||||
_rect.right = stream.readUint16LE();
|
||||
_rect.bottom = stream.readUint16LE();
|
||||
|
||||
stream.skip(6 * sizeof(uint16));
|
||||
uint32 nameOffset = stream.readUint32LE();
|
||||
uint32 examTextOffset = stream.readUint32LE();
|
||||
|
||||
byte c;
|
||||
stream.seek(nameOffset);
|
||||
_name.clear();
|
||||
while ((c = stream.readByte()))
|
||||
_name += c;
|
||||
|
||||
stream.seek(examTextOffset);
|
||||
_examText.clear();
|
||||
while ((c = stream.readByte()))
|
||||
_examText += c;
|
||||
stream.seek(pos + 32);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
48
engines/prince/mob.h
Normal file
48
engines/prince/mob.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Mob {
|
||||
public:
|
||||
Mob() {}
|
||||
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
|
||||
|
||||
bool _visible;
|
||||
uint16 _type;
|
||||
Common::Rect _rect;
|
||||
Common::String _name;
|
||||
Common::String _examText;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -7,6 +7,9 @@ MODULE_OBJS = \
|
|||
mhwanh.o \
|
||||
detection.o \
|
||||
font.o \
|
||||
mob.o \
|
||||
object.o \
|
||||
sound.o \
|
||||
prince.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
|
|
77
engines/prince/object.cpp
Normal file
77
engines/prince/object.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "prince/object.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Object::Object() : _surface(NULL) {
|
||||
}
|
||||
|
||||
void Object::loadSurface(Common::SeekableReadStream &stream) {
|
||||
stream.skip(4);
|
||||
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(stream.readUint16LE(), stream.readUint16LE(), Graphics::PixelFormat::createFormatCLUT8());
|
||||
for (int h = 0; h < _surface->h; ++h) {
|
||||
stream.read(_surface->getBasePtr(0, h), _surface->w);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Object::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
|
||||
int32 pos = stream.pos();
|
||||
uint16 x = stream.readUint16LE();
|
||||
if (x == 0xFFFF)
|
||||
return false;
|
||||
_x = x;
|
||||
_y = stream.readUint16LE();
|
||||
|
||||
const Common::String obStreamName = Common::String::format("OB%02d", stream.readUint16LE());
|
||||
Common::SeekableReadStream *obStream = SearchMan.createReadStreamForMember(obStreamName);
|
||||
if (!obStream) {
|
||||
error("Can't load %s", obStreamName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
loadSurface(*obStream);
|
||||
delete obStream;
|
||||
|
||||
_z = stream.readUint16LE();
|
||||
|
||||
stream.seek(pos + 16);
|
||||
|
||||
debug("Object x %d, y %d, z %d", _x, _y, _z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
47
engines/prince/object.h
Normal file
47
engines/prince/object.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_OBJECT_H
|
||||
#define PRINCE_OBJECT_H
|
||||
|
||||
#include "graphics/decoders/image_decoder.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Object {
|
||||
public:
|
||||
Object();
|
||||
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
Graphics::Surface *getSurface() const { return _surface; }
|
||||
|
||||
private:
|
||||
void loadSurface(Common::SeekableReadStream &stream);
|
||||
|
||||
Graphics::Surface *_surface;
|
||||
uint16 _x, _y, _z;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -47,17 +47,46 @@
|
|||
#include "prince/graphics.h"
|
||||
#include "prince/script.h"
|
||||
#include "prince/debugger.h"
|
||||
#include "prince/object.h"
|
||||
#include "prince/mob.h"
|
||||
#include "prince/sound.h"
|
||||
|
||||
#include "video/flic_decoder.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Graphics::Surface *loadCursor(const char *curName)
|
||||
{
|
||||
Common::SeekableReadStream *curStream = SearchMan.createReadStreamForMember(curName);
|
||||
if (!curStream) {
|
||||
error("Can't load %s", curName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curStream->skip(4);
|
||||
uint16 w = curStream->readUint16LE();
|
||||
uint16 h = curStream->readUint16LE();
|
||||
|
||||
debug("Loading cursor %s, w %d, h %d", curName, w, h);
|
||||
|
||||
Graphics::Surface *curSurface = new Graphics::Surface();
|
||||
curSurface->create(w, h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
for (int ih = 0; ih < h; ++ih) {
|
||||
curStream->read(curSurface->getBasePtr(0, ih), w);
|
||||
}
|
||||
|
||||
delete curStream;
|
||||
return curSurface;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) :
|
||||
Engine(syst), _gameDescription(gameDesc), _graph(NULL), _script(NULL),
|
||||
_locationNr(0), _debugger(NULL) {
|
||||
_locationNr(0), _debugger(NULL), _objectList(NULL), _mobList(NULL), _midiPlayer(NULL) {
|
||||
_rnd = new Common::RandomSource("prince");
|
||||
_debugger = new Debugger(this);
|
||||
|
||||
_midiPlayer = new MusicPlayer(this);
|
||||
}
|
||||
|
||||
PrinceEngine::~PrinceEngine() {
|
||||
|
@ -65,6 +94,9 @@ PrinceEngine::~PrinceEngine() {
|
|||
|
||||
delete _rnd;
|
||||
delete _debugger;
|
||||
delete _cur1;
|
||||
delete _cur2;
|
||||
delete _midiPlayer;
|
||||
}
|
||||
|
||||
GUI::Debugger *PrinceEngine::getDebugger() {
|
||||
|
@ -108,23 +140,59 @@ Common::Error PrinceEngine::run() {
|
|||
|
||||
delete skryptStream;
|
||||
|
||||
Common::SeekableReadStream *logoStrema = SearchMan.createReadStreamForMember("logo.raw");
|
||||
if (logoStrema)
|
||||
|
||||
_cur1 = loadCursor("mouse1.cur");
|
||||
_cur2 = loadCursor("mouse2.cur");
|
||||
|
||||
Common::SeekableReadStream *logoStream = SearchMan.createReadStreamForMember("logo.raw");
|
||||
if (logoStream)
|
||||
{
|
||||
MhwanhDecoder logo;
|
||||
logo.loadStream(*logoStrema);
|
||||
logo.loadStream(*logoStream);
|
||||
_graph->setPalette(logo.getPalette());
|
||||
_graph->draw(logo.getSurface());
|
||||
_graph->update();
|
||||
_system->delayMillis(700);
|
||||
}
|
||||
delete logoStrema;
|
||||
delete logoStream;
|
||||
|
||||
mainLoop();
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
class MobList {
|
||||
public:
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
|
||||
Common::Array<Mob> _mobList;
|
||||
};
|
||||
|
||||
bool MobList::loadFromStream(Common::SeekableReadStream &stream)
|
||||
{
|
||||
Mob mob;
|
||||
while (mob.loadFromStream(stream))
|
||||
_mobList.push_back(mob);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class ObjectList {
|
||||
public:
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
|
||||
Common::Array<Object> _objList;
|
||||
};
|
||||
|
||||
bool ObjectList::loadFromStream(Common::SeekableReadStream &stream)
|
||||
{
|
||||
Object obj;
|
||||
while (obj.loadFromStream(stream))
|
||||
_objList.push_back(obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadLocation(uint16 locationNr) {
|
||||
debug("PrinceEngine::loadLocation %d", locationNr);
|
||||
const Common::FSNode gameDataDir(ConfMan.get("path"));
|
||||
|
@ -145,14 +213,75 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
|
|||
|
||||
if(_roomBmp.loadStream(*room)) {
|
||||
debug("Room bitmap loaded");
|
||||
_system->getPaletteManager()->setPalette(_roomBmp.getPalette(), 0, 256);
|
||||
}
|
||||
|
||||
delete room;
|
||||
|
||||
delete _mobList;
|
||||
_mobList = NULL;
|
||||
|
||||
Common::SeekableReadStream *mobListStream = SearchMan.createReadStreamForMember("mob.lst");
|
||||
if (!mobListStream) {
|
||||
error("Can't read mob.lst");
|
||||
return false;
|
||||
}
|
||||
|
||||
_mobList = new MobList();
|
||||
_mobList->loadFromStream(*mobListStream);
|
||||
|
||||
delete mobListStream;
|
||||
|
||||
delete _objectList;
|
||||
_objectList = NULL;
|
||||
|
||||
Common::SeekableReadStream *objListStream = SearchMan.createReadStreamForMember("obj.lst");
|
||||
if (!objListStream) {
|
||||
error("Can't read obj.lst");
|
||||
return false;
|
||||
}
|
||||
|
||||
_objectList = new ObjectList();
|
||||
_objectList->loadFromStream(*objListStream);
|
||||
delete objListStream;
|
||||
|
||||
const char *musName = MusicPlayer::_musTable[MusicPlayer::_musRoomTable[locationNr]];
|
||||
_midiPlayer->loadMidi(musName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrinceEngine::changeCursor(uint16 curId)
|
||||
{
|
||||
Graphics::Surface *curSurface = NULL;
|
||||
|
||||
uint16 hotspotX = 0;
|
||||
uint16 hotspotY = 0;
|
||||
|
||||
switch(curId) {
|
||||
case 0:
|
||||
CursorMan.showMouse(false);
|
||||
return;
|
||||
case 1:
|
||||
curSurface = _cur1;
|
||||
break;
|
||||
case 2:
|
||||
curSurface = _cur2;
|
||||
hotspotX = curSurface->w >> 1;
|
||||
hotspotY = curSurface->h >> 1;
|
||||
break;
|
||||
}
|
||||
|
||||
CursorMan.replaceCursorPalette(_roomBmp.getPalette(), 0, 255);
|
||||
CursorMan.replaceCursor(
|
||||
curSurface->getBasePtr(0, 0),
|
||||
curSurface->w, curSurface->h,
|
||||
hotspotX, hotspotY,
|
||||
255, false,
|
||||
&curSurface->format
|
||||
);
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
bool PrinceEngine::playNextFrame() {
|
||||
const Graphics::Surface *s = _flicPlayer.decodeNextFrame();
|
||||
if (s) {
|
||||
|
@ -193,9 +322,46 @@ void PrinceEngine::keyHandler(Common::Event event) {
|
|||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::hotspot() {
|
||||
Common::Point mousepos = _system->getEventManager()->getMousePos();
|
||||
|
||||
Common::Array<Mob>::iterator it = _mobList->_mobList.begin();
|
||||
for (; it != _mobList->_mobList.end(); ++it) {
|
||||
if (it->_visible)
|
||||
continue;
|
||||
if (it->_rect.contains(mousepos)) {
|
||||
uint16 textW = 0;
|
||||
for (int i = 0; i < it->_name.size(); ++i)
|
||||
textW += _font.getCharWidth(it->_name[i]);
|
||||
|
||||
uint16 x = mousepos.x - textW/2;
|
||||
if (x > _graph->_frontScreen->w)
|
||||
x = 0;
|
||||
|
||||
if (x + textW > _graph->_frontScreen->w)
|
||||
x = _graph->_frontScreen->w - textW;
|
||||
|
||||
_font.drawString(
|
||||
_graph->_frontScreen,
|
||||
it->_name,
|
||||
x,
|
||||
mousepos.y - _font.getFontHeight(),
|
||||
_graph->_frontScreen->w,
|
||||
216
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::mainLoop() {
|
||||
|
||||
loadLocation(1);
|
||||
changeCursor(1);
|
||||
CursorMan.showMouse(true);
|
||||
|
||||
while (!shouldQuit()) {
|
||||
_debugger->onFrame();
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
while (eventMan->pollEvent(event)) {
|
||||
|
@ -223,13 +389,22 @@ void PrinceEngine::mainLoop() {
|
|||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
_script->step();
|
||||
//_script->step();
|
||||
|
||||
if (_roomBmp.getSurface())
|
||||
if (_roomBmp.getSurface()) {
|
||||
_graph->setPalette(_roomBmp.getPalette());
|
||||
_graph->draw(_roomBmp.getSurface());
|
||||
}
|
||||
|
||||
playNextFrame();
|
||||
|
||||
//debug("Cursor visible %d", CursorMan.isVisible());
|
||||
|
||||
//if (_objectList)
|
||||
// _graph->drawTransparent(_objectList->getSurface());
|
||||
|
||||
hotspot();
|
||||
|
||||
_graph->update();
|
||||
|
||||
_system->delayMillis(40);
|
||||
|
|
|
@ -53,6 +53,9 @@ class PrinceEngine;
|
|||
class GraphicsMan;
|
||||
class Script;
|
||||
class Debugger;
|
||||
class ObjectList;
|
||||
class MobList;
|
||||
class MusicPlayer;
|
||||
|
||||
class PrinceEngine : public Engine {
|
||||
protected:
|
||||
|
@ -77,19 +80,28 @@ public:
|
|||
|
||||
virtual GUI::Debugger *getDebugger();
|
||||
|
||||
void changeCursor(uint16 curId);
|
||||
|
||||
private:
|
||||
bool playNextFrame();
|
||||
void keyHandler(Common::Event event);
|
||||
void hotspot();
|
||||
|
||||
Common::RandomSource *_rnd;
|
||||
Graphics::BitmapDecoder _roomBmp;
|
||||
uint16 _locationNr;
|
||||
MhwanhDecoder _walizkaBmp;
|
||||
|
||||
Graphics::Surface *_cur1;
|
||||
Graphics::Surface *_cur2;
|
||||
|
||||
Debugger *_debugger;
|
||||
GraphicsMan *_graph;
|
||||
Script *_script;
|
||||
Font _font;
|
||||
ObjectList *_objectList;
|
||||
MobList *_mobList;
|
||||
MusicPlayer *_midiPlayer;
|
||||
|
||||
void mainLoop();
|
||||
|
||||
|
|
|
@ -206,24 +206,48 @@ void Script::O_REMBACKANIM() {
|
|||
debugScript("O_REMBACKANIM roomId %d, slot %d", roomId, slot);
|
||||
}
|
||||
|
||||
void Script::O_CHECKBACKANIMFRAME() {}
|
||||
void Script::O_CHECKBACKANIMFRAME() {
|
||||
uint16 slotId = readScript16bits();
|
||||
uint16 frameId = readScript16bits();
|
||||
|
||||
void Script::O_FREEALLSAMPLES() {}
|
||||
debugScript("O_CHECKBACKANIMFRAME slotId %d, frameId %d", slotId, frameId);
|
||||
}
|
||||
|
||||
void Script::O_SETMUSIC() {}
|
||||
void Script::O_FREEALLSAMPLES() {
|
||||
debugScript("O_FREEALLSAMPLES");
|
||||
}
|
||||
|
||||
void Script::O_STOPMUSIC() {}
|
||||
void Script::O_SETMUSIC() {
|
||||
uint16 musicId = readScript16bits();
|
||||
|
||||
void Script::O__WAIT() {}
|
||||
debugScript("O_SETMUSIC musicId %d", musicId);
|
||||
}
|
||||
|
||||
void Script::O_UPDATEOFF() {}
|
||||
void Script::O_STOPMUSIC() {
|
||||
debugScript("O_STOPMUSIC");
|
||||
}
|
||||
|
||||
void Script::O_UPDATEON() {}
|
||||
void Script::O__WAIT() {
|
||||
uint16 pause = readScript16bits();
|
||||
|
||||
void Script::O_UPDATE () {}
|
||||
debugScript("O__WAIT pause %d", pause);
|
||||
}
|
||||
|
||||
void Script::O_CLS() {}
|
||||
void Script::O_UPDATEOFF() {
|
||||
debugScript("O_UPDATEOFF");
|
||||
}
|
||||
|
||||
void Script::O_UPDATEON() {
|
||||
debugScript("O_UPDATEON");
|
||||
}
|
||||
|
||||
void Script::O_UPDATE () {
|
||||
debugScript("O_UPDATE");
|
||||
}
|
||||
|
||||
void Script::O_CLS() {
|
||||
debugScript("O_CLS");
|
||||
}
|
||||
|
||||
void Script::O__CALL() {
|
||||
int32 address = readScript32bits();
|
||||
|
@ -247,7 +271,10 @@ void Script::O_GO() {
|
|||
debugScript("O_GO 0x%04X", opPC);
|
||||
_currentInstruction += opPC - 4;
|
||||
}
|
||||
void Script::O_BACKANIMUPDATEOFF() {}
|
||||
void Script::O_BACKANIMUPDATEOFF() {
|
||||
uint16 slotId = readScript32bits();
|
||||
debugScript("O_BACKANIMUPDATEOFF slotId %d", slotId);
|
||||
}
|
||||
|
||||
void Script::O_BACKANIMUPDATEON() {
|
||||
uint16 slot = readScript16bits();
|
||||
|
@ -258,26 +285,39 @@ void Script::O_CHANGECURSOR() {
|
|||
uint16 cursorId = readScript16bits();
|
||||
debugScript("O_CHANGECURSOR %x", cursorId);
|
||||
}
|
||||
void Script::O_CHANGEANIMTYPE() {}
|
||||
|
||||
void Script::O_CHANGEANIMTYPE() {
|
||||
// NOT IMPLEMENTED
|
||||
}
|
||||
|
||||
void Script::O__SETFLAG() {
|
||||
uint16 flagId = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
if (value & 0x8000) {
|
||||
value = _flags[value - 0x8000];
|
||||
}
|
||||
|
||||
debugScript("O__SETFLAG 0x%04X %d", flagId, value);
|
||||
_flags[flagId-0x8000] = value;
|
||||
_flags[flagId - 0x8000] = value;
|
||||
}
|
||||
|
||||
void Script::O_COMPARE() {
|
||||
uint16 flagId = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
if (value & 0x8000) {
|
||||
value = _flags[value - 0x8000];
|
||||
}
|
||||
|
||||
debugScript("O_COMPARE flagId 0x%04X, value %d", flagId, value);
|
||||
_result = (_flags[flagId-0x8000] == value);
|
||||
_result = (_flags[flagId - 0x8000] == value);
|
||||
}
|
||||
|
||||
void Script::O_JUMPZ() {
|
||||
int32 offset = readScript32bits();
|
||||
debugScript("O_JUMPZ offset 0x%04X", offset);
|
||||
if (_result == 0)
|
||||
{
|
||||
if (! _result) {
|
||||
_currentInstruction += offset - 4;
|
||||
}
|
||||
}
|
||||
|
@ -285,20 +325,26 @@ void Script::O_JUMPZ() {
|
|||
void Script::O_JUMPNZ() {
|
||||
int32 offset = readScript32bits();
|
||||
debugScript("O_JUMPNZ offset 0x%04X", offset);
|
||||
if (_result)
|
||||
{
|
||||
if (_result) {
|
||||
_currentInstruction += offset - 4;
|
||||
}
|
||||
}
|
||||
|
||||
void Script::O_EXIT() {}
|
||||
void Script::O_EXIT() {
|
||||
uint16 exitCode = readScript16bits();
|
||||
debugScript("O_EXIT exitCode %d", exitCode);
|
||||
}
|
||||
|
||||
void Script::O_ADDFLAG() {
|
||||
uint16 flagId = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
_flags[flagId-0x8000] += value;
|
||||
if (_flags[flagId-0x8000])
|
||||
if (value & 0x8000) {
|
||||
value = _flags[value - 0x8000];
|
||||
}
|
||||
|
||||
_flags[flagId - 0x8000] += value;
|
||||
if (_flags[flagId - 0x8000])
|
||||
_result = 1;
|
||||
else
|
||||
_result = 0;
|
||||
|
@ -317,8 +363,12 @@ void Script::O_SUBFLAG() {
|
|||
uint16 flagId = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
_flags[flagId-0x8000] -= value;
|
||||
if (_flags[flagId-0x8000])
|
||||
if (value & 0x8000) {
|
||||
value = _flags[value - 0x8000];
|
||||
}
|
||||
|
||||
_flags[flagId - 0x8000] -= value;
|
||||
if (_flags[flagId - 0x8000])
|
||||
_result = 1;
|
||||
else
|
||||
_result = 0;
|
||||
|
@ -332,17 +382,84 @@ void Script::O_SETSTRING() {
|
|||
debugScript("O_SETSTRING 0x%04X", offset);
|
||||
}
|
||||
|
||||
void Script::O_ANDFLAG() {}
|
||||
void Script::O_ANDFLAG() {
|
||||
uint16 flagId = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
void Script::O_GETMOBDATA() {}
|
||||
debugScript("O_ANDFLAG flagId %d, value %d", flagId, value);
|
||||
|
||||
void Script::O_ORFLAG() {}
|
||||
if (value & 0x8000) {
|
||||
value = _flags[value - 0x8000];
|
||||
}
|
||||
|
||||
void Script::O_SETMOBDATA() {}
|
||||
_flags[flagId - 0x8000] &= value;
|
||||
|
||||
void Script::O_XORFLAG() {}
|
||||
if (_flags[flagId - 0x8000]) {
|
||||
_result = 1;
|
||||
} else {
|
||||
_result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Script::O_GETMOBTEXT() {}
|
||||
void Script::O_GETMOBDATA() {
|
||||
uint16 flagId = readScript16bits();
|
||||
uint16 mobId = readScript16bits();
|
||||
uint16 mobOffset = readScript16bits();
|
||||
|
||||
debugScript("O_GETMOBDATA flagId %d, modId %d, mobOffset %d", flagId, mobId, mobOffset);
|
||||
}
|
||||
|
||||
void Script::O_ORFLAG() {
|
||||
uint16 flagId = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
debugScript("O_ORFLAG flagId %d, value %d", flagId, value);
|
||||
|
||||
if (value & 0x8000) {
|
||||
value = _flags[value - 0x8000];
|
||||
}
|
||||
|
||||
_flags[flagId - 0x8000] |= value;
|
||||
|
||||
if (_flags[flagId - 0x8000]) {
|
||||
_result = 1;
|
||||
} else {
|
||||
_result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Script::O_SETMOBDATA() {
|
||||
uint16 mobId = readScript16bits();
|
||||
uint16 mobOffset = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
debugScript("O_SETMOBDATA mobId %d, mobOffset %d, value %d", mobId, mobOffset, value);
|
||||
}
|
||||
|
||||
void Script::O_XORFLAG() {
|
||||
uint16 flagId = readScript16bits();
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
debugScript("O_XORFLAG flagId %d, value %d", flagId, value);
|
||||
|
||||
if (value & 0x8000) {
|
||||
value = _flags[value - 0x8000];
|
||||
}
|
||||
|
||||
_flags[flagId - 0x8000] ^= value;
|
||||
|
||||
if (_flags[flagId - 0x8000]) {
|
||||
_result = 1;
|
||||
} else {
|
||||
_result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Script::O_GETMOBTEXT() {
|
||||
uint16 value = readScript16bits();
|
||||
|
||||
debugScript("O_GETMOBTEXT value %d", value);
|
||||
}
|
||||
|
||||
void Script::O_MOVEHERO() {
|
||||
uint16 heroId = readScript16bits();
|
||||
|
|
160
engines/prince/sound.cpp
Normal file
160
engines/prince/sound.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on original Soltys source code
|
||||
* Copyright (c) 1994-1995 Janus B. Wisniewski and L.K. Avalon
|
||||
*/
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/sound.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/archive.h"
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "audio/audiostream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
const char * MusicPlayer::_musTable[] = {
|
||||
"",
|
||||
"Battlfld.mid",
|
||||
"Cave.mid",
|
||||
"Cemetery.mid",
|
||||
"Credits.mid",
|
||||
"Fjord.mid",
|
||||
"Guitar.mid",
|
||||
"Hell.mid",
|
||||
"Jingle.mid",
|
||||
"Main.mid",
|
||||
"Night.mid",
|
||||
"Reality.mid",
|
||||
"Sunlord.mid",
|
||||
"Tavern.mid",
|
||||
"Temple.mid",
|
||||
"Boruta.mid",
|
||||
"Intro.mid"
|
||||
};
|
||||
|
||||
const uint8 MusicPlayer::_musRoomTable[] = {
|
||||
0,
|
||||
3,
|
||||
9,
|
||||
9,
|
||||
9,
|
||||
13,
|
||||
9,
|
||||
9
|
||||
};
|
||||
|
||||
|
||||
MusicPlayer::MusicPlayer(PrinceEngine *vm) : _vm(vm) {
|
||||
_data = NULL;
|
||||
_isGM = false;
|
||||
|
||||
MidiPlayer::createDriver();
|
||||
|
||||
int ret = _driver->open();
|
||||
if (ret == 0) {
|
||||
if (_nativeMT32)
|
||||
_driver->sendMT32Reset();
|
||||
else
|
||||
_driver->sendGMReset();
|
||||
|
||||
// TODO: Load cmf.ins with the instrument table. It seems that an
|
||||
// interface for such an operation is supported for AdLib. Maybe for
|
||||
// this card, setting instruments is necessary.
|
||||
|
||||
_driver->setTimerCallback(this, &timerCallback);
|
||||
}
|
||||
}
|
||||
|
||||
MusicPlayer::~MusicPlayer() {
|
||||
killMidi();
|
||||
}
|
||||
|
||||
void MusicPlayer::killMidi() {
|
||||
Audio::MidiPlayer::stop();
|
||||
|
||||
free(_data);
|
||||
_data = NULL;
|
||||
}
|
||||
|
||||
void MusicPlayer::loadMidi(const char * name) {
|
||||
Common::SeekableReadStream * stream = SearchMan.createReadStreamForMember(name);
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
// Stop any currently playing MIDI file
|
||||
killMidi();
|
||||
|
||||
// Read in the data for the file
|
||||
_dataSize = stream->size();
|
||||
_data = (byte *)malloc(_dataSize);
|
||||
stream->read(_data, _dataSize);
|
||||
|
||||
// Start playing the music
|
||||
sndMidiStart();
|
||||
}
|
||||
|
||||
void MusicPlayer::sndMidiStart() {
|
||||
_isGM = true;
|
||||
|
||||
MidiParser *parser = MidiParser::createParser_SMF();
|
||||
if (parser->loadMusic(_data, _dataSize)) {
|
||||
parser->setTrack(0);
|
||||
parser->setMidiDriver(this);
|
||||
parser->setTimerRate(_driver->getBaseTempo());
|
||||
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
|
||||
|
||||
_parser = parser;
|
||||
|
||||
syncVolume();
|
||||
|
||||
// Al the tracks are supposed to loop
|
||||
_isLooping = true;
|
||||
_isPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MusicPlayer::send(uint32 b) {
|
||||
if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
|
||||
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
|
||||
}
|
||||
|
||||
Audio::MidiPlayer::send(b);
|
||||
}
|
||||
|
||||
void MusicPlayer::sendToChannel(byte channel, uint32 b) {
|
||||
if (!_channelsTable[channel]) {
|
||||
_channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
|
||||
// If a new channel is allocated during the playback, make sure
|
||||
// its volume is correctly initialized.
|
||||
if (_channelsTable[channel])
|
||||
_channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
|
||||
}
|
||||
|
||||
if (_channelsTable[channel])
|
||||
_channelsTable[channel]->send(b);
|
||||
}
|
||||
|
||||
} // End of namespace CGE
|
73
engines/prince/sound.h
Normal file
73
engines/prince/sound.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on original Soltys source code
|
||||
* Copyright (c) 1994-1995 Janus B. Wisniewski and L.K. Avalon
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_SOUND_H
|
||||
#define PRINCE_SOUND_H
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/decoders/wave.h"
|
||||
#include "audio/fmopl.h"
|
||||
#include "audio/mididrv.h"
|
||||
#include "audio/midiparser.h"
|
||||
#include "audio/midiplayer.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class PrinceEngine;
|
||||
|
||||
class MusicPlayer: public Audio::MidiPlayer {
|
||||
private:
|
||||
PrinceEngine *_vm;
|
||||
byte *_data;
|
||||
int _dataSize;
|
||||
bool _isGM;
|
||||
|
||||
// Start MIDI File
|
||||
void sndMidiStart();
|
||||
|
||||
// Stop MIDI File
|
||||
void sndMidiStop();
|
||||
public:
|
||||
MusicPlayer(PrinceEngine *vm);
|
||||
~MusicPlayer();
|
||||
|
||||
void loadMidi(const char *);
|
||||
void killMidi();
|
||||
|
||||
virtual void send(uint32 b);
|
||||
virtual void sendToChannel(byte channel, uint32 b);
|
||||
|
||||
static const char * _musTable[];
|
||||
static const uint8 _musRoomTable[];
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue