MYST3: More opcodes, frame mode.

This commit is contained in:
Bastien Bouclet 2011-09-05 20:13:48 +02:00
parent f594450710
commit 1e2f4b4313
17 changed files with 683 additions and 111 deletions

View File

@ -71,7 +71,7 @@ Common::String Console::describeCondition(int16 condition) {
bool Console::Cmd_Infos(int argc, const char **argv) {
uint16 nodeId = _vm->_node->getId();
uint16 nodeId = _vm->_currentNode;
uint16 roomId = 0;
if (argc >= 2) {
@ -176,7 +176,7 @@ bool Console::Cmd_ListNodes(int argc, const char **argv) {
}
bool Console::Cmd_Run(int argc, const char **argv) {
uint16 nodeId = _vm->_node->getId();
uint16 nodeId = _vm->_currentNode;
uint16 roomId = 0;
if (argc >= 2) {

View File

@ -36,7 +36,7 @@ class DirectorySubEntry {
byte _type;
public:
enum ResourceType {kFaceTexture, kFaceMask};
enum ResourceType {kCubeFace, kFaceMask, kFrame = 6};
void readFromStream(Common::SeekableReadStream &inStream);
void dump();

View File

@ -24,7 +24,7 @@
namespace Myst3 {
bool HotSpot::isPointInRects(const Common::Point & p)
bool HotSpot::isPointInRectsCube(const Common::Point &p)
{
for(uint j = 0;j < rects.size();j++){
Common::Rect rect = Common::Rect(
@ -40,4 +40,20 @@ bool HotSpot::isPointInRects(const Common::Point & p)
return false;
}
bool HotSpot::isPointInRectsFrame(const Common::Point &p)
{
for(uint j = 0;j < rects.size();j++){
Common::Rect rect = Common::Rect(
rects[j].centerHeading,
rects[j].centerPitch,
rects[j].width,
rects[j].height);
if(rect.contains(p)){
return true;
}
}
return false;
}
} /* namespace Myst3 */

View File

@ -52,7 +52,8 @@ public:
int16 unk2;
Common::Array<Opcode> script;
bool isPointInRects(const Common::Point &p);
bool isPointInRectsCube(const Common::Point &p);
bool isPointInRectsFrame(const Common::Point & p);
};

View File

@ -10,6 +10,8 @@ MODULE_OBJS := \
hotspot.o \
myst3.o \
node.o \
nodecube.o \
nodeframe.o \
scene.o \
script.o \
variables.o

View File

@ -32,8 +32,10 @@
#include "engines/engine.h"
#include "engines/myst3/myst3.h"
#include "engines/myst3/database.h"
#include "engines/myst3/myst3.h"
#include "engines/myst3/nodecube.h"
#include "engines/myst3/nodeframe.h"
#include "engines/myst3/variables.h"
#include "graphics/jpeg.h"
@ -62,7 +64,6 @@ Myst3Engine::~Myst3Engine() {
DebugMan.clearAllDebugChannels();
delete _scene;
delete _node;
delete _archive;
delete _db;
delete _scriptEngine;
@ -79,16 +80,16 @@ Common::Error Myst3Engine::run() {
_db = new Database("M3.exe");
_vars = new Variables(this);
_scene = new Scene();
_node = new Node();
_archive = new Archive();
goToNode(1, 245); // LEIS
_system->setupScreen(w, h, false, true);
_system->showMouse(false);
_scene->init(w, h);
_node->load(*_archive, 1);
// Var init script
runScriptsFromNode(1000, 101);
goToNode(1, 245); // LEIS
for(;;) {
// Process events
@ -98,14 +99,35 @@ Common::Error Myst3Engine::run() {
if (event.type == Common::EVENT_QUIT) {
return Common::kNoError;
} else if (event.type == Common::EVENT_MOUSEMOVE) {
_scene->updateCamera(event.relMouse);
if (_viewType == kCube) {
_scene->updateCamera(event.relMouse);
}
} else if (event.type == Common::EVENT_LBUTTONDOWN) {
Common::Point mouse = _scene->getMousePos();
NodePtr nodeData = _db->getNodeData(_node->getId());
NodePtr nodeData = _db->getNodeData(_currentNode);
if (_viewType == kCube) {
Common::Point mouse = _scene->getMousePos();
for (uint j = 0; j < nodeData->hotspots.size(); j++) {
if (nodeData->hotspots[j].isPointInRects(mouse)) {
_scriptEngine->run(&nodeData->hotspots[j].script);
for (uint j = 0; j < nodeData->hotspots.size(); j++) {
if (nodeData->hotspots[j].isPointInRectsCube(mouse)) {
_scriptEngine->run(&nodeData->hotspots[j].script);
}
}
} else if (_viewType == kFrame) {
static const uint originalWidth = 640;
static const uint originalHeight = 480;
static const uint frameHeight = 360;
Common::Point mouse = _system->getEventManager()->getMousePos();
Common::Point scaledMouse = Common::Point(
mouse.x * originalWidth / _system->getWidth(),
CLIP<uint>(mouse.y * originalHeight / _system->getHeight()
- (originalHeight - 360) / 2, 0, frameHeight));
for (uint j = 0; j < nodeData->hotspots.size(); j++) {
if (nodeData->hotspots[j].isPointInRectsFrame(scaledMouse)) {
_scriptEngine->run(&nodeData->hotspots[j].script);
}
}
}
} else if (event.type == Common::EVENT_KEYDOWN) {
@ -124,8 +146,12 @@ Common::Error Myst3Engine::run() {
}
_scene->clear();
_scene->setupCamera();
if (_viewType == kFrame) {
_scene->setupCameraFrame();
} else {
_scene->setupCameraCube();
}
_node->draw();
_system->updateScreen();
@ -133,12 +159,20 @@ Common::Error Myst3Engine::run() {
}
_node->unload();
delete _node;
_archive->close();
return Common::kNoError;
}
void Myst3Engine::goToNode(uint16 nodeID, uint8 roomID) {
if (_node) {
_node->unload();
delete _node;
_node = 0;
}
loadNode(nodeID, roomID);
}
@ -154,8 +188,6 @@ void Myst3Engine::loadNode(uint16 nodeID, uint8 roomID, uint32 ageID) {
if (ageID)
_currentAge = _vars->valueOrVarValue(ageID);
_node->unload();
char oldRoomName[8];
char newRoomName[8];
_db->getRoomName(oldRoomName);
@ -191,7 +223,20 @@ void Myst3Engine::runNodeInitScripts() {
}
void Myst3Engine::loadNodeCubeFaces(uint16 nodeID) {
_viewType = 1;
_viewType = kCube;
_system->showMouse(false);
_node = new NodeCube();
_node->load(*_archive, nodeID);
}
void Myst3Engine::loadNodeFrame(uint16 nodeID) {
_viewType = kFrame;
_system->showMouse(true);
_node = new NodeFrame();
_node->load(*_archive, nodeID);
}

View File

@ -44,6 +44,12 @@ enum {
kDebugScript = (1 << 3)
};
// View type
enum ViewType {
kCube = 1,
kFrame = 2
};
class Console;
class Variables;
@ -62,6 +68,7 @@ public:
void goToNode(uint16 nodeID, uint8 roomID = 0);
void loadNode(uint16 nodeID, uint8 roomID = 0, uint32 ageID = 0);
void loadNodeCubeFaces(uint16 nodeID);
void loadNodeFrame(uint16 nodeID);
void runScriptsFromNode(uint16 nodeID, uint8 roomID = 0, uint32 ageID = 0);
void runNodeInitScripts();
@ -75,7 +82,7 @@ private:
Script *_scriptEngine;
Database *_db;
uint _viewType;
ViewType _viewType;
uint16 _currentNode;
uint8 _currentRoom;
uint32 _currentAge;

View File

@ -102,85 +102,10 @@ void Node::dumpFaceMask(Archive &archive, uint16 index, int face) {
delete[] mask;
}
void Node::load(Archive &archive, uint16 index) {
for (int i = 0; i < 6; i++) {
Common::MemoryReadStream *jpegStream = archive.dumpToMemory(index, i + 1, DirectorySubEntry::kFaceTexture);
if (jpegStream) {
Graphics::JPEG jpeg;
jpeg.read(jpegStream);
setFaceTextureJPEG(i, &jpeg);
}
}
_id = index;
}
void Node::unload() {
for (int i = 0; i < 6; i++) {
glDeleteTextures(1, &_cubeTextures[i]);
}
}
void Node::draw() {
// Size of the cube
float t = 1.0f;
// Used fragment of the textures
float s = 640 / (float)_cubeTextureSize;
glDepthMask(GL_FALSE);
glBindTexture(GL_TEXTURE_2D, _cubeTextures[4]);
glBegin(GL_TRIANGLE_STRIP); // X-
glTexCoord2f(0, s); glVertex3f(-t,-t, t);
glTexCoord2f(s, s); glVertex3f(-t,-t,-t);
glTexCoord2f(0, 0); glVertex3f(-t, t, t);
glTexCoord2f(s, 0); glVertex3f(-t, t,-t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[3]);
glBegin(GL_TRIANGLE_STRIP); // X+
glTexCoord2f(0, s); glVertex3f( t,-t,-t);
glTexCoord2f(s, s); glVertex3f( t,-t, t);
glTexCoord2f(0, 0); glVertex3f( t, t,-t);
glTexCoord2f(s, 0); glVertex3f( t, t, t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[1]);
glBegin(GL_TRIANGLE_STRIP); // Y-
glTexCoord2f(0, s); glVertex3f( t,-t,-t);
glTexCoord2f(s, s); glVertex3f(-t,-t,-t);
glTexCoord2f(0, 0); glVertex3f( t,-t, t);
glTexCoord2f(s, 0); glVertex3f(-t,-t, t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[5]);
glBegin(GL_TRIANGLE_STRIP); // Y+
glTexCoord2f(0, s); glVertex3f( t, t, t);
glTexCoord2f(s, s); glVertex3f(-t, t, t);
glTexCoord2f(0, 0); glVertex3f( t, t,-t);
glTexCoord2f(s, 0); glVertex3f(-t, t,-t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[0]);
glBegin(GL_TRIANGLE_STRIP); // Z-
glTexCoord2f(0, s); glVertex3f(-t,-t,-t);
glTexCoord2f(s, s); glVertex3f( t,-t,-t);
glTexCoord2f(0, 0); glVertex3f(-t, t,-t);
glTexCoord2f(s, 0); glVertex3f( t, t,-t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[2]);
glBegin(GL_TRIANGLE_STRIP); // Z+
glTexCoord2f(0, s); glVertex3f( t,-t, t);
glTexCoord2f(s, s); glVertex3f(-t,-t, t);
glTexCoord2f(0, 0); glVertex3f( t, t, t);
glTexCoord2f(s, 0); glVertex3f(-t, t, t);
glEnd();
glDepthMask(GL_TRUE);
}
} // end of namespace Myst3

View File

@ -39,21 +39,18 @@
namespace Myst3 {
class Node {
private:
protected:
static const int _cubeTextureSize = 1024;
GLuint _cubeTextures[6];
uint16 _id;
public:
void setFaceTextureRGB(int face, Graphics::Surface *texture);
void setFaceTextureJPEG(int face, Graphics::JPEG *jpeg);
void draw();
void load(Archive &archive, uint16 id);
virtual void draw() = 0;
virtual void load(Archive &archive, uint16 id) = 0;
void unload();
void dumpFaceMask(Archive &archive, uint16 index, int face);
uint16 getId() { return _id; }
virtual ~Node() {};
};
} // end of namespace Myst3

110
engines/myst3/nodecube.cpp Normal file
View File

@ -0,0 +1,110 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include "engines/myst3/nodecube.h"
namespace Myst3 {
NodeCube::NodeCube() {
}
NodeCube::~NodeCube() {
}
void NodeCube::load(Archive &archive, uint16 index) {
for (int i = 0; i < 6; i++) {
Common::MemoryReadStream *jpegStream = archive.dumpToMemory(index, i + 1, DirectorySubEntry::kCubeFace);
if (jpegStream) {
Graphics::JPEG jpeg;
jpeg.read(jpegStream);
setFaceTextureJPEG(i, &jpeg);
delete jpegStream;
}
}
}
void NodeCube::draw() {
// Size of the cube
float t = 1.0f;
// Used fragment of the textures
float s = 640 / (float)_cubeTextureSize;
glDepthMask(GL_FALSE);
glBindTexture(GL_TEXTURE_2D, _cubeTextures[4]);
glBegin(GL_TRIANGLE_STRIP); // X-
glTexCoord2f(0, s); glVertex3f(-t,-t, t);
glTexCoord2f(s, s); glVertex3f(-t,-t,-t);
glTexCoord2f(0, 0); glVertex3f(-t, t, t);
glTexCoord2f(s, 0); glVertex3f(-t, t,-t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[3]);
glBegin(GL_TRIANGLE_STRIP); // X+
glTexCoord2f(0, s); glVertex3f( t,-t,-t);
glTexCoord2f(s, s); glVertex3f( t,-t, t);
glTexCoord2f(0, 0); glVertex3f( t, t,-t);
glTexCoord2f(s, 0); glVertex3f( t, t, t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[1]);
glBegin(GL_TRIANGLE_STRIP); // Y-
glTexCoord2f(0, s); glVertex3f( t,-t,-t);
glTexCoord2f(s, s); glVertex3f(-t,-t,-t);
glTexCoord2f(0, 0); glVertex3f( t,-t, t);
glTexCoord2f(s, 0); glVertex3f(-t,-t, t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[5]);
glBegin(GL_TRIANGLE_STRIP); // Y+
glTexCoord2f(0, s); glVertex3f( t, t, t);
glTexCoord2f(s, s); glVertex3f(-t, t, t);
glTexCoord2f(0, 0); glVertex3f( t, t,-t);
glTexCoord2f(s, 0); glVertex3f(-t, t,-t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[0]);
glBegin(GL_TRIANGLE_STRIP); // Z-
glTexCoord2f(0, s); glVertex3f(-t,-t,-t);
glTexCoord2f(s, s); glVertex3f( t,-t,-t);
glTexCoord2f(0, 0); glVertex3f(-t, t,-t);
glTexCoord2f(s, 0); glVertex3f( t, t,-t);
glEnd();
glBindTexture(GL_TEXTURE_2D, _cubeTextures[2]);
glBegin(GL_TRIANGLE_STRIP); // Z+
glTexCoord2f(0, s); glVertex3f( t,-t, t);
glTexCoord2f(s, s); glVertex3f(-t,-t, t);
glTexCoord2f(0, 0); glVertex3f( t, t, t);
glTexCoord2f(s, 0); glVertex3f(-t, t, t);
glEnd();
glDepthMask(GL_TRUE);
}
} /* namespace Myst3 */

40
engines/myst3/nodecube.h Normal file
View File

@ -0,0 +1,40 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#ifndef NODECUBE_H_
#define NODECUBE_H_
#include "engines/myst3/node.h"
namespace Myst3 {
class NodeCube: public Myst3::Node {
public:
NodeCube();
virtual ~NodeCube();
void load(Archive &archive, uint16 id);
void draw();
};
} /* namespace Myst3 */
#endif /* NODECUBE_H_ */

View File

@ -0,0 +1,68 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include "engines/myst3/nodeframe.h"
namespace Myst3 {
NodeFrame::NodeFrame() {
}
NodeFrame::~NodeFrame() {
}
void NodeFrame::load(Archive &archive, uint16 index) {
Common::MemoryReadStream *jpegStream = archive.dumpToMemory(index, 1, DirectorySubEntry::kFrame);
if (jpegStream) {
Graphics::JPEG jpeg;
jpeg.read(jpegStream);
setFaceTextureJPEG(0, &jpeg);
delete jpegStream;
}
}
void NodeFrame::draw() {
// Size of the frame
float t = 0.85f;
float s = 360.0f / 640.0f * t;
// Used fragment of texture
float u = 640 / (float)_cubeTextureSize;
float v = 360 / (float)_cubeTextureSize;
glDepthMask(GL_FALSE);
glBindTexture(GL_TEXTURE_2D, _cubeTextures[0]);
glBegin(GL_TRIANGLE_STRIP); // Z+
glTexCoord2f(0, v); glVertex3f( t,-s, 1.0f);
glTexCoord2f(u, v); glVertex3f(-t,-s, 1.0f);
glTexCoord2f(0, 0); glVertex3f( t, s, 1.0f);
glTexCoord2f(u, 0); glVertex3f(-t, s, 1.0f);
glEnd();
glDepthMask(GL_TRUE);
}
} /* namespace Myst3 */

40
engines/myst3/nodeframe.h Normal file
View File

@ -0,0 +1,40 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#ifndef NODEFRAME_H_
#define NODEFRAME_H_
#include "engines/myst3/node.h"
namespace Myst3 {
class NodeFrame : public Node {
public:
NodeFrame();
virtual ~NodeFrame();
void load(Archive &archive, uint16 id);
void draw();
};
} /* namespace Myst3 */
#endif /* NODEFRAME_H_ */

View File

@ -18,9 +18,6 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*
*/
#include "engines/myst3/scene.h"
@ -35,7 +32,7 @@ Scene::Scene():
void Scene::init(int width, int height) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);
gluPerspective(65.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@ -50,7 +47,13 @@ void Scene::clear() {
glColor3f(1.0f, 1.0f, 1.0f);
}
void Scene::setupCamera() {
void Scene::setupCameraFrame() {
glLoadIdentity();
glRotatef(0.0, -1.0f, 0.0f, 0.0f);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
}
void Scene::setupCameraCube() {
// Rotate the model to simulate the rotation of the camera
glLoadIdentity();
glRotatef(_cameraPitch, -1.0f, 0.0f, 0.0f);

View File

@ -48,7 +48,8 @@ class Scene {
void init(int width, int height);
void clear();
void setupCamera();
void setupCameraCube();
void setupCameraFrame();
void updateCamera(Common::Point &mouse);
Common::Point getMousePos() { return Common::Point(_cameraHeading, _cameraPitch); }

View File

@ -32,6 +32,10 @@ Script::Script(Myst3Engine *vm):
#define OPCODE(op, x) _commands.push_back(Command(op, &Script::x, #x))
OPCODE(4, nodeCubeInit);
OPCODE(6, nodeCubeInitIndex);
OPCODE(7, nodeFrameInit);
OPCODE(8, nodeFrameInitCond);
OPCODE(9, nodeFrameInitIndex);
OPCODE(11, stopWholeScript);
OPCODE(35, sunspotAdd);
OPCODE(49, varSetZero);
@ -39,6 +43,26 @@ Script::Script(Myst3Engine *vm):
OPCODE(51, varSetTwo);
OPCODE(52, varSetOneHundred);
OPCODE(53, varSetValue);
OPCODE(54, varToggle);
OPCODE(55, varSetOneIfZero);
OPCODE(67, varRemoveBits);
OPCODE(68, varToggleBits);
OPCODE(69, varCopy);
OPCODE(70, varSetBitsFromVar);
OPCODE(71, varSetBits);
OPCODE(72, varApplyMask);
OPCODE(73, varSwap);
OPCODE(74, varIncrement);
OPCODE(75, varIncrementMax);
OPCODE(76, varIncrementMaxLooping);
OPCODE(77, varAddValueMaxLooping);
OPCODE(78, varDecrement);
OPCODE(79, varDecrementMin);
OPCODE(80, varAddValueMax);
OPCODE(81, varSubValueMin);
OPCODE(82, varZeroRange);
OPCODE(83, varCopyRange);
OPCODE(84, varSetRange);
OPCODE(85, varIncrementMaxTen);
OPCODE(86, varAddValue);
OPCODE(87, varArrayAddValue);
@ -135,6 +159,61 @@ void Script::nodeCubeInit(Context &c, const Opcode &cmd) {
// TODO: Load rects
}
void Script::nodeCubeInitIndex(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node cube init indexed %d",
cmd.op, cmd.args[0]);
uint16 var = _vm->_vars->get(cmd.args[0]);
if (var >= cmd.args.size() - 1)
error("Opcode %d, invalid index %d", cmd.op, var);
uint16 value = cmd.args[var + 1];
uint16 nodeId = _vm->_vars->valueOrVarValue(value);
_vm->loadNodeCubeFaces(nodeId);
// TODO: Load rects
}
void Script::nodeFrameInit(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node frame init %d", cmd.op, cmd.args[0]);
uint16 nodeId = _vm->_vars->valueOrVarValue(cmd.args[0]);
_vm->loadNodeFrame(nodeId);
// TODO: Load rects
}
void Script::nodeFrameInitCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node frame init condition %d ? %d : %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint16 value;
if (_vm->_vars->evaluate(cmd.args[0]))
value = cmd.args[1];
else
value = cmd.args[2];
uint16 nodeId = _vm->_vars->valueOrVarValue(value);
_vm->loadNodeFrame(nodeId);
// TODO: Load rects
}
void Script::nodeFrameInitIndex(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node frame init indexed %d",
cmd.op, cmd.args[0]);
uint16 var = _vm->_vars->get(cmd.args[0]);
if (var >= cmd.args.size() - 1)
error("Opcode %d, invalid index %d", cmd.op, var);
uint16 value = cmd.args[var + 1];
uint16 nodeId = _vm->_vars->valueOrVarValue(value);
_vm->loadNodeFrame(nodeId);
// TODO: Load rects
}
void Script::stopWholeScript(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Stop whole script", cmd.op);
@ -178,6 +257,220 @@ void Script::varSetValue(Context &c, const Opcode &cmd) {
_vm->_vars->set(cmd.args[0], cmd.args[1]);
}
void Script::varToggle(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Toggle var %d", cmd.op, cmd.args[0]);
_vm->_vars->set(cmd.args[0], _vm->_vars->get(cmd.args[0]) == 0);
}
void Script::varSetOneIfZero(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var %d to one if zero", cmd.op, cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
if (!value)
_vm->_vars->set(cmd.args[0], 1);
}
void Script::varRemoveBits(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Remove bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value &= ~cmd.args[1];
_vm->_vars->set(cmd.args[0], value);
}
void Script::varToggleBits(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Toggle bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value ^= cmd.args[1];
_vm->_vars->set(cmd.args[0], value);
}
void Script::varCopy(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Copy var %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_vars->set(cmd.args[1], _vm->_vars->get(cmd.args[0]));
}
void Script::varSetBitsFromVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set bits from var %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value |= _vm->_vars->get(cmd.args[1]);
_vm->_vars->set(cmd.args[0], value);
}
void Script::varSetBits(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set bits %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value |= cmd.args[1];
_vm->_vars->set(cmd.args[0], value);
}
void Script::varApplyMask(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Apply mask %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value &= cmd.args[1];
_vm->_vars->set(cmd.args[0], value);
}
void Script::varSwap(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Swap var %d and var %d", cmd.op, cmd.args[0], cmd.args[1]);
uint32 value = _vm->_vars->get(cmd.args[0]);
_vm->_vars->set(cmd.args[0], _vm->_vars->get(cmd.args[1]));
_vm->_vars->set(cmd.args[1], value);
}
void Script::varIncrement(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d", cmd.op, cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value++;
_vm->_vars->set(cmd.args[0], value);
}
void Script::varIncrementMax(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d with max value %d",
cmd.op, cmd.args[0], cmd.args[1]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value++;
if (value > cmd.args[1])
value = cmd.args[1];
_vm->_vars->set(cmd.args[0], value);
}
void Script::varIncrementMaxLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d in range [%d, %d]",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value++;
if (value > cmd.args[2])
value = cmd.args[1];
_vm->_vars->set(cmd.args[0], value);
}
void Script::varAddValueMaxLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add %d to var %d in range [%d, %d]",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
uint32 value = _vm->_vars->get(cmd.args[1]);
value += cmd.args[0];
if (value > cmd.args[3])
value = cmd.args[2];
_vm->_vars->set(cmd.args[1], value);
}
void Script::varDecrement(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Decrement var %d", cmd.op, cmd.args[0]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value--;
_vm->_vars->set(cmd.args[0], value);
}
void Script::varDecrementMin(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Decrement var %d with min value %d",
cmd.op, cmd.args[0], cmd.args[1]);
uint32 value = _vm->_vars->get(cmd.args[0]);
value--;
if (value < cmd.args[1])
value = cmd.args[1];
_vm->_vars->set(cmd.args[0], value);
}
void Script::varAddValueMax(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add value %d to var %d with max value %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint32 value = _vm->_vars->get(cmd.args[1]);
value += cmd.args[0];
if (value > cmd.args[2])
value = cmd.args[2];
_vm->_vars->set(cmd.args[1], value);
}
void Script::varSubValueMin(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Substract value %d from var %d with min value %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint32 value = _vm->_vars->get(cmd.args[1]);
value -= cmd.args[0];
if (value < cmd.args[2])
value = cmd.args[2];
_vm->_vars->set(cmd.args[1], value);
}
void Script::varZeroRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to zero", cmd.op, cmd.args[0], cmd.args[1]);
if (cmd.args[0] > cmd.args[1])
error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
for (uint i = cmd.args[0]; i <= cmd.args[1]; i++)
_vm->_vars->set(i, 0);
}
void Script::varCopyRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Copy vars from %d to %d, length: %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
if (cmd.args[2] <= 0)
return;
for (uint i = 0; i < cmd.args[2]; i++)
_vm->_vars->set(cmd.args[1] + i, _vm->_vars->get(cmd.args[0] + i));
}
void Script::varSetRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to val %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
if (cmd.args[0] > cmd.args[1])
error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
for (uint i = cmd.args[0]; i <= cmd.args[1]; i++)
_vm->_vars->set(i, cmd.args[2]);
}
void Script::varIncrementMaxTen(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d max 10", cmd.op, cmd.args[0]);

View File

@ -65,6 +65,10 @@ private:
void runOp(Context &c, const Opcode &op);
DECLARE_OPCODE(nodeCubeInit);
DECLARE_OPCODE(nodeCubeInitIndex);
DECLARE_OPCODE(nodeFrameInit);
DECLARE_OPCODE(nodeFrameInitCond);
DECLARE_OPCODE(nodeFrameInitIndex);
DECLARE_OPCODE(stopWholeScript);
DECLARE_OPCODE(sunspotAdd);
DECLARE_OPCODE(varSetZero);
@ -72,6 +76,26 @@ private:
DECLARE_OPCODE(varSetTwo);
DECLARE_OPCODE(varSetOneHundred);
DECLARE_OPCODE(varSetValue);
DECLARE_OPCODE(varToggle);
DECLARE_OPCODE(varSetOneIfZero);
DECLARE_OPCODE(varRemoveBits);
DECLARE_OPCODE(varToggleBits);
DECLARE_OPCODE(varCopy);
DECLARE_OPCODE(varSetBitsFromVar);
DECLARE_OPCODE(varSetBits);
DECLARE_OPCODE(varApplyMask);
DECLARE_OPCODE(varSwap);
DECLARE_OPCODE(varIncrement);
DECLARE_OPCODE(varIncrementMax);
DECLARE_OPCODE(varIncrementMaxLooping);
DECLARE_OPCODE(varAddValueMaxLooping);
DECLARE_OPCODE(varDecrement);
DECLARE_OPCODE(varDecrementMin);
DECLARE_OPCODE(varAddValueMax);
DECLARE_OPCODE(varSubValueMin);
DECLARE_OPCODE(varZeroRange);
DECLARE_OPCODE(varCopyRange);
DECLARE_OPCODE(varSetRange);
DECLARE_OPCODE(varIncrementMaxTen);
DECLARE_OPCODE(varAddValue);
DECLARE_OPCODE(varArrayAddValue);