399 lines
9.4 KiB
C
Raw Normal View History

2013-10-13 22:34:26 +01:00
/* 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.
2016-09-03 12:46:38 +02:00
*
2013-10-13 22:34:26 +01:00
* 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.
2016-09-03 12:46:38 +02:00
*
2013-10-13 22:34:26 +01:00
* 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_SCRIPT_H
#define PRINCE_SCRIPT_H
#include "common/random.h"
2013-12-10 00:26:42 +00:00
#include "common/endian.h"
2013-12-13 07:05:37 +00:00
#include "common/array.h"
2014-08-01 17:38:04 +02:00
#include "common/stream.h"
2013-11-04 11:28:10 +00:00
#include "prince/flags.h"
2013-10-13 22:34:26 +01:00
namespace Prince {
class PrinceEngine;
class Animation;
class Object;
struct Anim;
2014-05-23 21:24:05 +02:00
struct BackgroundAnim;
struct Mask;
2013-10-13 22:34:26 +01:00
2013-12-13 07:05:37 +00:00
class Room {
public:
Room();
int _mobs; // mob flag offset
int _backAnim; // offset to array of animation numbers
int _obj; // offset to array of object numbers
int _nak; // offset to array of masks
int _itemUse;
int _itemGive;
int _walkTo; // offset to array of WALKTO events or 0
int _examine; // offset to array of EXAMINE events or 0
int _pickup;
int _use;
int _pushOpen;
int _pullClose;
int _talk;
int _give;
2013-12-13 07:05:37 +00:00
2014-10-07 02:14:12 +02:00
bool loadStream(Common::SeekableReadStream &stream);
bool loadRoom(byte *roomData);
int getOptionOffset(int option);
2013-12-13 07:05:37 +00:00
private:
typedef void (Room::*LoadingStep)(Common::SeekableReadStream &stream);
void nextLoadStep(Common::SeekableReadStream &stream, LoadingStep step);
void loadMobs(Common::SeekableReadStream &stream);
void loadBackAnim(Common::SeekableReadStream &stream);
void loadObj(Common::SeekableReadStream &stream);
void loadNak(Common::SeekableReadStream &stream);
void loadItemUse(Common::SeekableReadStream &stream);
void loadItemGive(Common::SeekableReadStream &stream);
void loadWalkTo(Common::SeekableReadStream &stream);
void loadExamine(Common::SeekableReadStream &stream);
void loadPickup(Common::SeekableReadStream &stream);
void loadUse(Common::SeekableReadStream &stream);
void loadPushOpen(Common::SeekableReadStream &stream);
void loadPullClose(Common::SeekableReadStream &stream);
void loadTalk(Common::SeekableReadStream &stream);
void loadGive(Common::SeekableReadStream &stream);
};
2013-10-24 20:31:08 +01:00
class Script {
2013-10-13 22:34:26 +01:00
public:
static const int16 kMaxRooms = 60;
Script(PrinceEngine *vm);
2013-12-10 00:26:42 +00:00
~Script();
2013-10-13 22:34:26 +01:00
struct ScriptInfo {
int rooms;
int startGame;
int restoreGame;
int stdExamine;
int stdPickup;
int stdUse;
int stdOpen;
int stdClose;
int stdTalk;
int stdGive;
int usdCode;
int invObjExam;
int invObjUse;
int invObjUU;
int stdUseItem;
int lightSources;
int specRout;
int invObjGive;
int stdGiveItem;
int goTester;
};
ScriptInfo _scriptInfo;
2014-10-07 02:14:12 +02:00
bool loadStream(Common::SeekableReadStream &stream);
2013-10-13 22:34:26 +01:00
uint16 readScript16(uint32 address);
uint32 readScript32(uint32 address);
2013-12-10 00:26:42 +00:00
uint32 getStartGameOffset();
uint32 getLocationInitScript(int initRoomTableOffset, int roomNr);
int16 getLightX(int locationNr);
int16 getLightY(int locationNr);
int32 getShadowScale(int locationNr);
uint8 *getRoomOffset(int locationNr);
int32 getOptionStandardOffset(int option);
uint8 *getHeroAnimName(int offset);
void installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset);
void installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset);
void installObjects(int offset);
bool loadAllMasks(Common::Array<Mask> &maskList, int offset);
2013-12-10 00:26:42 +00:00
2014-06-19 01:08:38 +02:00
int scanMobEvents(int mobMask, int dataEventOffset);
int scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask);
byte getMobVisible(int roomMobOffset, uint16 mob);
void setMobVisible(int roomMobOffset, uint16 mob, byte value);
uint32 getBackAnimId(int roomBackAnimOffset, int slot);
void setBackAnimId(int roomBackAnimOffset, int slot, int animId);
byte getObjId(int roomObjOffset, int slot);
void setObjId(int roomObjOffset, int slot, byte objectId);
2013-12-10 00:26:42 +00:00
const char *getString(uint32 offset) {
return (const char *)(&_data[offset]);
}
private:
PrinceEngine *_vm;
2013-12-10 00:26:42 +00:00
uint8 *_data;
uint32 _dataSize;
2013-12-13 07:05:37 +00:00
Common::Array<Room> _roomList;
2013-12-10 00:26:42 +00:00
};
class InterpreterFlags {
public:
InterpreterFlags();
2014-07-30 19:54:39 +02:00
void setFlagValue(Flags::Id flag, int32 value);
int32 getFlagValue(Flags::Id flag);
2013-10-13 22:34:26 +01:00
2013-12-10 00:26:42 +00:00
void resetAllFlags();
static const uint16 kFlagMask = 0x8000;
static const uint16 kMaxFlags = 2000;
2013-12-10 00:26:42 +00:00
private:
int32 _flags[kMaxFlags];
2013-12-10 00:26:42 +00:00
};
class Interpreter {
public:
Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags);
void stopBg() { _bgOpcodePC = 0; }
void stepBg();
void stepFg();
void storeNewPC(int opcodePC);
2014-07-18 15:35:43 +02:00
int getLastOPCode();
2014-07-25 15:21:31 +02:00
int getFgOpcodePC();
void setBgOpcodePC(uint32 value);
void setFgOpcodePC(uint32 value);
uint32 getCurrentString();
void setCurrentString(uint32 value);
2013-12-10 00:26:42 +00:00
2014-07-03 04:19:52 +02:00
byte *getString();
void setString(byte *newString);
void increaseString();
void setResult(byte value);
2013-10-13 22:34:26 +01:00
private:
2013-10-30 02:28:07 +00:00
PrinceEngine *_vm;
2013-12-10 00:26:42 +00:00
Script *_script;
InterpreterFlags *_flags;
2013-10-30 02:28:07 +00:00
uint32 _currentInstruction;
2013-11-04 11:28:10 +00:00
uint32 _bgOpcodePC;
uint32 _fgOpcodePC;
2013-10-30 02:28:07 +00:00
uint16 _lastOpcode;
uint32 _lastInstruction;
byte _result;
2013-12-10 00:26:42 +00:00
bool _opcodeNF; // break interpreter loop
bool _opcodeEnd; // end of a game flag
2013-11-04 11:28:10 +00:00
2013-10-30 02:28:07 +00:00
static const uint32 _STACK_SIZE = 500;
uint32 _stack[_STACK_SIZE];
2014-07-23 15:07:54 +02:00
struct stringStack {
byte *string;
byte *dialogData;
uint32 currentString;
} _stringStack;
2013-10-30 02:28:07 +00:00
uint8 _stacktop;
2013-11-02 02:02:53 +00:00
uint32 _waitFlag;
2013-10-30 02:28:07 +00:00
byte *_string;
uint32 _currentString;
2013-11-04 16:07:19 +00:00
const char *_mode;
2013-10-30 02:28:07 +00:00
// Helper functions
2013-11-04 11:28:10 +00:00
uint32 step(uint32 opcodePC);
uint16 readScript16();
uint32 readScript32();
int32 readScriptFlagValue();
2013-12-10 00:26:42 +00:00
Flags::Id readScriptFlagId();
int checkSeq(byte *string);
2013-12-10 00:26:42 +00:00
void debugInterpreter(const char *s, ...);
2013-10-30 02:28:07 +00:00
2013-12-10 00:26:42 +00:00
typedef void (Interpreter::*OpcodeFunc)();
2013-10-30 02:28:07 +00:00
static OpcodeFunc _opcodes[];
static const uint kGiveLetterScriptFix = 79002;
static const uint kSecondBirdAnimationScriptFix = 45658;
2014-08-07 02:20:52 +02:00
// Keep opcode handlers names as they are in original code
// making it easier to switch back and forth
2013-10-30 02:28:07 +00:00
void O_WAITFOREVER();
void O_BLACKPALETTE();
void O_SETUPPALETTE();
void O_INITROOM();
void O_SETSAMPLE();
void O_FREESAMPLE();
void O_PLAYSAMPLE();
void O_PUTOBJECT();
void O_REMOBJECT();
void O_SHOWANIM();
void O_CHECKANIMEND();
void O_FREEANIM();
void O_CHECKANIMFRAME();
void O_PUTBACKANIM();
void O_REMBACKANIM();
void O_CHECKBACKANIMFRAME();
void O_FREEALLSAMPLES();
void O_SETMUSIC();
void O_STOPMUSIC();
void O__WAIT();
void O_UPDATEOFF();
void O_UPDATEON();
void O_UPDATE ();
void O_CLS();
void O__CALL();
void O_RETURN();
void O_GO();
void O_BACKANIMUPDATEOFF();
void O_BACKANIMUPDATEON();
void O_CHANGECURSOR();
void O_CHANGEANIMTYPE();
void O__SETFLAG();
void O_COMPARE();
void O_JUMPZ();
void O_JUMPNZ();
void O_EXIT();
void O_ADDFLAG();
void O_TALKANIM();
void O_SUBFLAG();
void O_SETSTRING();
void O_ANDFLAG();
void O_GETMOBDATA();
void O_ORFLAG();
void O_SETMOBDATA();
void O_XORFLAG();
void O_GETMOBTEXT();
void O_MOVEHERO();
void O_WALKHERO();
void O_SETHERO();
void O_HEROOFF();
void O_HEROON();
void O_CLSTEXT();
void O_CALLTABLE();
void O_CHANGEMOB();
void O_ADDINV();
void O_REMINV();
void O_REPINV();
void O_OBSOLETE_GETACTION();
void O_ADDWALKAREA();
void O_REMWALKAREA();
void O_RESTOREWALKAREA();
void O_WAITFRAME();
void O_SETFRAME();
void O_RUNACTION();
void O_COMPAREHI();
void O_COMPARELO();
void O_PRELOADSET();
void O_FREEPRELOAD();
void O_CHECKINV();
void O_TALKHERO();
void O_WAITTEXT();
void O_SETHEROANIM();
void O_WAITHEROANIM();
void O_GETHERODATA();
void O_GETMOUSEBUTTON();
void O_CHANGEFRAMES();
void O_CHANGEBACKFRAMES();
void O_GETBACKANIMDATA();
void O_GETANIMDATA();
void O_SETBGCODE();
void O_SETBACKFRAME();
void O_GETRND();
void O_TALKBACKANIM();
void O_LOADPATH();
void O_GETCHAR();
void O_SETDFLAG();
void O_CALLDFLAG();
void O_PRINTAT();
void O_ZOOMIN();
void O_ZOOMOUT();
void O_SETSTRINGOFFSET();
void O_GETOBJDATA();
void O_SETOBJDATA();
void O_SWAPOBJECTS();
void O_CHANGEHEROSET();
void O_ADDSTRING();
void O_SUBSTRING();
void O_INITDIALOG();
void O_ENABLEDIALOGOPT();
void O_DISABLEDIALOGOPT();
void O_SHOWDIALOGBOX();
void O_STOPSAMPLE();
void O_BACKANIMRANGE();
void O_CLEARPATH();
void O_SETPATH();
void O_GETHEROX();
void O_GETHEROY();
void O_GETHEROD();
void O_PUSHSTRING();
void O_POPSTRING();
void O_SETFGCODE();
void O_STOPHERO();
void O_ANIMUPDATEOFF();
void O_ANIMUPDATEON();
void O_FREECURSOR();
void O_ADDINVQUIET();
void O_RUNHERO();
void O_SETBACKANIMDATA();
void O_VIEWFLC();
void O_CHECKFLCFRAME();
void O_CHECKFLCEND();
void O_FREEFLC();
void O_TALKHEROSTOP();
void O_HEROCOLOR();
void O_GRABMAPA();
void O_ENABLENAK();
void O_DISABLENAK();
void O_GETMOBNAME();
void O_SWAPINVENTORY();
void O_CLEARINVENTORY();
void O_SKIPTEXT();
void O_SETVOICEH();
void O_SETVOICEA();
void O_SETVOICEB();
void O_SETVOICEC();
void O_VIEWFLCLOOP();
void O_FLCSPEED();
void O_OPENINVENTORY();
void O_KRZYWA();
void O_GETKRZYWA();
void O_GETMOB();
void O_INPUTLINE();
void O_SETVOICED();
void O_BREAK_POINT();
2013-12-10 00:26:42 +00:00
2013-10-13 22:34:26 +01:00
};
2014-08-01 17:38:04 +02:00
} // End of namespace Prince
2013-10-13 22:34:26 +01:00
#endif