PRINCE: midi music player added. mob and object lists added

This commit is contained in:
Kamil Zbróg 2013-10-28 00:06:21 +00:00
parent 5357724657
commit 84784add68
16 changed files with 864 additions and 53 deletions

View file

@ -31,6 +31,8 @@ Debugger::Debugger(PrinceEngine *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag)); DCmd_Register("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag));
DCmd_Register("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag)); DCmd_Register("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag));
DCmd_Register("viewflc", WRAP_METHOD(Debugger, Cmd_ViewFlc)); 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) { static int strToInt(const char *s) {
@ -108,4 +110,29 @@ bool Debugger::Cmd_ViewFlc(int argc, const char **argv) {
_vm->loadAnim(flagNum); _vm->loadAnim(flagNum);
return true; 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;
}
} }

View file

@ -40,6 +40,8 @@ private:
bool Cmd_GetFlag(int argc, const char **argv); bool Cmd_GetFlag(int argc, const char **argv);
bool Cmd_ClearFlag(int argc, const char **argv); bool Cmd_ClearFlag(int argc, const char **argv);
bool Cmd_ViewFlc(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; PrinceEngine *_vm;
}; };

View file

@ -46,7 +46,6 @@ bool Font::load(Common::SeekableReadStream &stream) {
} }
int Font::getFontHeight() const { int Font::getFontHeight() const {
debug("Font::getFontHeight %d", _fontData[5]);
return _fontData[5]; return _fontData[5];
} }
@ -70,15 +69,20 @@ int Font::getCharWidth(byte chr) const {
return getChrData(chr)._width; 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 ChrData chrData = getChrData(chr);
const byte *src = chrData._pixels;
byte *target = (byte *)dst->getBasePtr(x, y);
for (int i = 0; i < chrData._height; i++) { for (int y = 0; y < chrData._height; ++y) {
memcpy(target, src, chrData._width); for (int x = 0; x < chrData._width; ++x) {
src += chrData._width; byte d = chrData._pixels[x + (chrData._width * y)];
target += dst->pitch; 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;
}
}
} }
} }

View file

@ -40,6 +40,7 @@ void GraphicsMan::update() {
_vm->_system->copyRectToScreen((byte*)_frontScreen->getBasePtr(0,0), 640, 0, 0, 640, 480); _vm->_system->copyRectToScreen((byte*)_frontScreen->getBasePtr(0,0), 640, 0, 0, 640, 480);
_vm->_system->updateScreen(); _vm->_system->updateScreen();
_changed = false;
} }
} }
@ -53,15 +54,19 @@ void GraphicsMan::change() {
void GraphicsMan::draw(const Graphics::Surface *s) void GraphicsMan::draw(const Graphics::Surface *s)
{ {
for (uint y = 0; y < 480; y++) uint16 w = MIN(_frontScreen->w, s->w);
memcpy((byte*)_frontScreen->getBasePtr(0, y), (byte*)s->getBasePtr(0, y), 640); for (uint y = 0; y < s->h; y++) {
change(); if (y < _frontScreen->h) {
memcpy((byte*)_frontScreen->getBasePtr(0, y), (byte*)s->getBasePtr(0, y), w);
}
}
change();
} }
void GraphicsMan::drawTransparent(const Graphics::Surface *s) void GraphicsMan::drawTransparent(const Graphics::Surface *s)
{ {
for (uint y = 0; y < 480; ++y) { for (uint y = 0; y < s->h; ++y) {
for (uint x = 0; x < 640; ++x) { for (uint x = 0; x < s->w; ++x) {
byte pixel = *((byte*)s->getBasePtr(x,y)); byte pixel = *((byte*)s->getBasePtr(x,y));
if (pixel != 255) { if (pixel != 255) {
*((byte*)_frontScreen->getBasePtr(x, y)) = pixel; *((byte*)_frontScreen->getBasePtr(x, y)) = pixel;

View file

@ -53,7 +53,6 @@ private:
PrinceEngine *_vm; PrinceEngine *_vm;
bool _changed; bool _changed;
byte _palette[3 * 256];
}; };
} }

View file

@ -28,8 +28,7 @@
namespace Prince { namespace Prince {
class MhwanhDecoder : public Graphics::ImageDecoder class MhwanhDecoder : public Graphics::ImageDecoder {
{
public: public:
MhwanhDecoder(); MhwanhDecoder();
virtual ~MhwanhDecoder(); virtual ~MhwanhDecoder();

63
engines/prince/mob.cpp Normal file
View 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
View 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;
};
}

View file

@ -7,6 +7,9 @@ MODULE_OBJS = \
mhwanh.o \ mhwanh.o \
detection.o \ detection.o \
font.o \ font.o \
mob.o \
object.o \
sound.o \
prince.o prince.o
# This module can be built as a plugin # This module can be built as a plugin

77
engines/prince/object.cpp Normal file
View 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
View file

@ -0,0 +1,47 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 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

View file

@ -47,17 +47,46 @@
#include "prince/graphics.h" #include "prince/graphics.h"
#include "prince/script.h" #include "prince/script.h"
#include "prince/debugger.h" #include "prince/debugger.h"
#include "prince/object.h"
#include "prince/mob.h"
#include "prince/sound.h"
#include "video/flic_decoder.h" #include "video/flic_decoder.h"
namespace Prince { 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) : PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _graph(NULL), _script(NULL), 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"); _rnd = new Common::RandomSource("prince");
_debugger = new Debugger(this); _debugger = new Debugger(this);
_midiPlayer = new MusicPlayer(this);
} }
PrinceEngine::~PrinceEngine() { PrinceEngine::~PrinceEngine() {
@ -65,6 +94,9 @@ PrinceEngine::~PrinceEngine() {
delete _rnd; delete _rnd;
delete _debugger; delete _debugger;
delete _cur1;
delete _cur2;
delete _midiPlayer;
} }
GUI::Debugger *PrinceEngine::getDebugger() { GUI::Debugger *PrinceEngine::getDebugger() {
@ -108,23 +140,59 @@ Common::Error PrinceEngine::run() {
delete skryptStream; 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; MhwanhDecoder logo;
logo.loadStream(*logoStrema); logo.loadStream(*logoStream);
_graph->setPalette(logo.getPalette()); _graph->setPalette(logo.getPalette());
_graph->draw(logo.getSurface()); _graph->draw(logo.getSurface());
_graph->update(); _graph->update();
_system->delayMillis(700); _system->delayMillis(700);
} }
delete logoStrema; delete logoStream;
mainLoop(); mainLoop();
return Common::kNoError; 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) { bool PrinceEngine::loadLocation(uint16 locationNr) {
debug("PrinceEngine::loadLocation %d", locationNr); debug("PrinceEngine::loadLocation %d", locationNr);
const Common::FSNode gameDataDir(ConfMan.get("path")); const Common::FSNode gameDataDir(ConfMan.get("path"));
@ -145,14 +213,75 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
if(_roomBmp.loadStream(*room)) { if(_roomBmp.loadStream(*room)) {
debug("Room bitmap loaded"); debug("Room bitmap loaded");
_system->getPaletteManager()->setPalette(_roomBmp.getPalette(), 0, 256);
} }
delete room; 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; 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() { bool PrinceEngine::playNextFrame() {
const Graphics::Surface *s = _flicPlayer.decodeNextFrame(); const Graphics::Surface *s = _flicPlayer.decodeNextFrame();
if (s) { 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() { void PrinceEngine::mainLoop() {
loadLocation(1);
changeCursor(1);
CursorMan.showMouse(true);
while (!shouldQuit()) { while (!shouldQuit()) {
_debugger->onFrame();
Common::Event event; Common::Event event;
Common::EventManager *eventMan = _system->getEventManager(); Common::EventManager *eventMan = _system->getEventManager();
while (eventMan->pollEvent(event)) { while (eventMan->pollEvent(event)) {
@ -223,13 +389,22 @@ void PrinceEngine::mainLoop() {
if (shouldQuit()) if (shouldQuit())
return; return;
_script->step(); //_script->step();
if (_roomBmp.getSurface()) if (_roomBmp.getSurface()) {
_graph->setPalette(_roomBmp.getPalette());
_graph->draw(_roomBmp.getSurface()); _graph->draw(_roomBmp.getSurface());
}
playNextFrame(); playNextFrame();
//debug("Cursor visible %d", CursorMan.isVisible());
//if (_objectList)
// _graph->drawTransparent(_objectList->getSurface());
hotspot();
_graph->update(); _graph->update();
_system->delayMillis(40); _system->delayMillis(40);

View file

@ -53,6 +53,9 @@ class PrinceEngine;
class GraphicsMan; class GraphicsMan;
class Script; class Script;
class Debugger; class Debugger;
class ObjectList;
class MobList;
class MusicPlayer;
class PrinceEngine : public Engine { class PrinceEngine : public Engine {
protected: protected:
@ -77,19 +80,28 @@ public:
virtual GUI::Debugger *getDebugger(); virtual GUI::Debugger *getDebugger();
void changeCursor(uint16 curId);
private: private:
bool playNextFrame(); bool playNextFrame();
void keyHandler(Common::Event event); void keyHandler(Common::Event event);
void hotspot();
Common::RandomSource *_rnd; Common::RandomSource *_rnd;
Graphics::BitmapDecoder _roomBmp; Graphics::BitmapDecoder _roomBmp;
uint16 _locationNr; uint16 _locationNr;
MhwanhDecoder _walizkaBmp; MhwanhDecoder _walizkaBmp;
Graphics::Surface *_cur1;
Graphics::Surface *_cur2;
Debugger *_debugger; Debugger *_debugger;
GraphicsMan *_graph; GraphicsMan *_graph;
Script *_script; Script *_script;
Font _font; Font _font;
ObjectList *_objectList;
MobList *_mobList;
MusicPlayer *_midiPlayer;
void mainLoop(); void mainLoop();

View file

@ -206,24 +206,48 @@ void Script::O_REMBACKANIM() {
debugScript("O_REMBACKANIM roomId %d, slot %d", roomId, slot); 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() { void Script::O__CALL() {
int32 address = readScript32bits(); int32 address = readScript32bits();
@ -247,7 +271,10 @@ void Script::O_GO() {
debugScript("O_GO 0x%04X", opPC); debugScript("O_GO 0x%04X", opPC);
_currentInstruction += opPC - 4; _currentInstruction += opPC - 4;
} }
void Script::O_BACKANIMUPDATEOFF() {} void Script::O_BACKANIMUPDATEOFF() {
uint16 slotId = readScript32bits();
debugScript("O_BACKANIMUPDATEOFF slotId %d", slotId);
}
void Script::O_BACKANIMUPDATEON() { void Script::O_BACKANIMUPDATEON() {
uint16 slot = readScript16bits(); uint16 slot = readScript16bits();
@ -258,26 +285,39 @@ void Script::O_CHANGECURSOR() {
uint16 cursorId = readScript16bits(); uint16 cursorId = readScript16bits();
debugScript("O_CHANGECURSOR %x", cursorId); debugScript("O_CHANGECURSOR %x", cursorId);
} }
void Script::O_CHANGEANIMTYPE() {}
void Script::O_CHANGEANIMTYPE() {
// NOT IMPLEMENTED
}
void Script::O__SETFLAG() { void Script::O__SETFLAG() {
uint16 flagId = readScript16bits(); uint16 flagId = readScript16bits();
uint16 value = readScript16bits(); uint16 value = readScript16bits();
if (value & 0x8000) {
value = _flags[value - 0x8000];
}
debugScript("O__SETFLAG 0x%04X %d", flagId, value); debugScript("O__SETFLAG 0x%04X %d", flagId, value);
_flags[flagId-0x8000] = value; _flags[flagId - 0x8000] = value;
} }
void Script::O_COMPARE() { void Script::O_COMPARE() {
uint16 flagId = readScript16bits(); uint16 flagId = readScript16bits();
uint16 value = readScript16bits(); uint16 value = readScript16bits();
if (value & 0x8000) {
value = _flags[value - 0x8000];
}
debugScript("O_COMPARE flagId 0x%04X, value %d", flagId, value); debugScript("O_COMPARE flagId 0x%04X, value %d", flagId, value);
_result = (_flags[flagId-0x8000] == value); _result = (_flags[flagId - 0x8000] == value);
} }
void Script::O_JUMPZ() { void Script::O_JUMPZ() {
int32 offset = readScript32bits(); int32 offset = readScript32bits();
debugScript("O_JUMPZ offset 0x%04X", offset); debugScript("O_JUMPZ offset 0x%04X", offset);
if (_result == 0) if (! _result) {
{
_currentInstruction += offset - 4; _currentInstruction += offset - 4;
} }
} }
@ -285,20 +325,26 @@ void Script::O_JUMPZ() {
void Script::O_JUMPNZ() { void Script::O_JUMPNZ() {
int32 offset = readScript32bits(); int32 offset = readScript32bits();
debugScript("O_JUMPNZ offset 0x%04X", offset); debugScript("O_JUMPNZ offset 0x%04X", offset);
if (_result) if (_result) {
{
_currentInstruction += offset - 4; _currentInstruction += offset - 4;
} }
} }
void Script::O_EXIT() {} void Script::O_EXIT() {
uint16 exitCode = readScript16bits();
debugScript("O_EXIT exitCode %d", exitCode);
}
void Script::O_ADDFLAG() { void Script::O_ADDFLAG() {
uint16 flagId = readScript16bits(); uint16 flagId = readScript16bits();
uint16 value = readScript16bits(); uint16 value = readScript16bits();
_flags[flagId-0x8000] += value; if (value & 0x8000) {
if (_flags[flagId-0x8000]) value = _flags[value - 0x8000];
}
_flags[flagId - 0x8000] += value;
if (_flags[flagId - 0x8000])
_result = 1; _result = 1;
else else
_result = 0; _result = 0;
@ -317,8 +363,12 @@ void Script::O_SUBFLAG() {
uint16 flagId = readScript16bits(); uint16 flagId = readScript16bits();
uint16 value = readScript16bits(); uint16 value = readScript16bits();
_flags[flagId-0x8000] -= value; if (value & 0x8000) {
if (_flags[flagId-0x8000]) value = _flags[value - 0x8000];
}
_flags[flagId - 0x8000] -= value;
if (_flags[flagId - 0x8000])
_result = 1; _result = 1;
else else
_result = 0; _result = 0;
@ -332,17 +382,84 @@ void Script::O_SETSTRING() {
debugScript("O_SETSTRING 0x%04X", offset); 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() { void Script::O_MOVEHERO() {
uint16 heroId = readScript16bits(); uint16 heroId = readScript16bits();

160
engines/prince/sound.cpp Normal file
View 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
View 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