aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Zbróg2013-10-28 00:06:21 +0000
committerKamil Zbróg2013-10-28 00:06:21 +0000
commit84784add6811aa1b285b70e139d0bdf9738c858c (patch)
treea957560ff8dd49d1826cfa8e01fd835270423324
parent5357724657bff809b10b1f2bfe8547d1b53d6dcb (diff)
downloadscummvm-rg350-84784add6811aa1b285b70e139d0bdf9738c858c.tar.gz
scummvm-rg350-84784add6811aa1b285b70e139d0bdf9738c858c.tar.bz2
scummvm-rg350-84784add6811aa1b285b70e139d0bdf9738c858c.zip
PRINCE: midi music player added. mob and object lists added
-rw-r--r--engines/prince/debugger.cpp27
-rw-r--r--engines/prince/debugger.h2
-rw-r--r--engines/prince/font.cpp20
-rw-r--r--engines/prince/graphics.cpp15
-rw-r--r--engines/prince/graphics.h1
-rw-r--r--engines/prince/mhwanh.h3
-rw-r--r--engines/prince/mob.cpp63
-rw-r--r--engines/prince/mob.h48
-rw-r--r--engines/prince/module.mk3
-rw-r--r--engines/prince/object.cpp77
-rw-r--r--engines/prince/object.h47
-rw-r--r--engines/prince/prince.cpp193
-rw-r--r--engines/prince/prince.h12
-rw-r--r--engines/prince/script.cpp173
-rw-r--r--engines/prince/sound.cpp160
-rw-r--r--engines/prince/sound.h73
16 files changed, 864 insertions, 53 deletions
diff --git a/engines/prince/debugger.cpp b/engines/prince/debugger.cpp
index 5da11acd88..817e4fb2b5 100644
--- a/engines/prince/debugger.cpp
+++ b/engines/prince/debugger.cpp
@@ -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;
+}
+
}
diff --git a/engines/prince/debugger.h b/engines/prince/debugger.h
index c5a8be60c6..dabcd970ea 100644
--- a/engines/prince/debugger.h
+++ b/engines/prince/debugger.h
@@ -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;
};
diff --git a/engines/prince/font.cpp b/engines/prince/font.cpp
index 8c72f1b912..aac790dfe0 100644
--- a/engines/prince/font.cpp
+++ b/engines/prince/font.cpp
@@ -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;
+ }
+ }
}
}
diff --git a/engines/prince/graphics.cpp b/engines/prince/graphics.cpp
index 74b46aad4c..94cab7bb37 100644
--- a/engines/prince/graphics.cpp
+++ b/engines/prince/graphics.cpp
@@ -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;
diff --git a/engines/prince/graphics.h b/engines/prince/graphics.h
index 0f12c734c6..0e29c5c97a 100644
--- a/engines/prince/graphics.h
+++ b/engines/prince/graphics.h
@@ -53,7 +53,6 @@ private:
PrinceEngine *_vm;
bool _changed;
- byte _palette[3 * 256];
};
}
diff --git a/engines/prince/mhwanh.h b/engines/prince/mhwanh.h
index 21822759e8..24472da7a5 100644
--- a/engines/prince/mhwanh.h
+++ b/engines/prince/mhwanh.h
@@ -28,8 +28,7 @@
namespace Prince {
-class MhwanhDecoder : public Graphics::ImageDecoder
-{
+class MhwanhDecoder : public Graphics::ImageDecoder {
public:
MhwanhDecoder();
virtual ~MhwanhDecoder();
diff --git a/engines/prince/mob.cpp b/engines/prince/mob.cpp
new file mode 100644
index 0000000000..caf44fef12
--- /dev/null
+++ b/engines/prince/mob.cpp
@@ -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;
+}
+
+}
diff --git a/engines/prince/mob.h b/engines/prince/mob.h
new file mode 100644
index 0000000000..5b2a6f9d6e
--- /dev/null
+++ b/engines/prince/mob.h
@@ -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;
+};
+
+}
+
diff --git a/engines/prince/module.mk b/engines/prince/module.mk
index a177e670ed..6b519d4d57 100644
--- a/engines/prince/module.mk
+++ b/engines/prince/module.mk
@@ -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
diff --git a/engines/prince/object.cpp b/engines/prince/object.cpp
new file mode 100644
index 0000000000..72d4f1103a
--- /dev/null
+++ b/engines/prince/object.cpp
@@ -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;
+}
+
+}
diff --git a/engines/prince/object.h b/engines/prince/object.h
new file mode 100644
index 0000000000..3a8859c196
--- /dev/null
+++ b/engines/prince/object.h
@@ -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
diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp
index 4fb2082baf..a9f243ce11 100644
--- a/engines/prince/prince.cpp
+++ b/engines/prince/prince.cpp
@@ -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);
diff --git a/engines/prince/prince.h b/engines/prince/prince.h
index b289c75553..6340733255 100644
--- a/engines/prince/prince.h
+++ b/engines/prince/prince.h
@@ -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();
diff --git a/engines/prince/script.cpp b/engines/prince/script.cpp
index d790d6d9c3..e2360debc8 100644
--- a/engines/prince/script.cpp
+++ b/engines/prince/script.cpp
@@ -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();
diff --git a/engines/prince/sound.cpp b/engines/prince/sound.cpp
new file mode 100644
index 0000000000..2e2e53e664
--- /dev/null
+++ b/engines/prince/sound.cpp
@@ -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
diff --git a/engines/prince/sound.h b/engines/prince/sound.h
new file mode 100644
index 0000000000..779fe563f9
--- /dev/null
+++ b/engines/prince/sound.h
@@ -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
+