Initial commit
This commit is contained in:
377
engines/glk/advsys/game.h
Normal file
377
engines/glk/advsys/game.h
Normal file
@@ -0,0 +1,377 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ADVSYS_GAME
|
||||
#define GLK_ADVSYS_GAME
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace AdvSys {
|
||||
|
||||
#define NIL 0
|
||||
#define MESSAGE_CACHE_SIZE 8
|
||||
#define MESSAGE_BLOCK_SIZE 512
|
||||
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
enum Action {
|
||||
A_VERBS = 0,
|
||||
A_PREPOSITIONS = 2,
|
||||
A_FLAG = 4,
|
||||
A_MASK = 5,
|
||||
A_CODE = 6,
|
||||
A_SIZE = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Word types
|
||||
*/
|
||||
enum WordType {
|
||||
WT_UNKNOWN = 0,
|
||||
WT_VERB = 1,
|
||||
WT_NOUN = 2,
|
||||
WT_ADJECTIVE = 3,
|
||||
WT_PREPOSITION = 4,
|
||||
WT_CONJUNCTION = 5,
|
||||
WT_ARTICLE = 6
|
||||
};
|
||||
|
||||
/**
|
||||
* Object fields
|
||||
*/
|
||||
enum ObjectField {
|
||||
O_CLASS = 0,
|
||||
O_NOUNS = 2,
|
||||
O_ADJECTIVES = 4,
|
||||
O_NPROPERTIES = 6,
|
||||
O_PROPERTIES = 8,
|
||||
O_SIZE = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Built-in variables
|
||||
*/
|
||||
enum Variable {
|
||||
V_ACTOR = 1, ///< Actor noun phrase number
|
||||
V_ACTION = 2, ///< Action from phrase
|
||||
V_DOBJECT = 3, ///< First direct object noun phrase number
|
||||
V_NDOBJECTS = 4, ///< Number of direct object noun phrases
|
||||
V_IOBJECT = 5, ///< Indirect object noun phrase number
|
||||
V_OCOUNT = 6 ///< Total object count
|
||||
};
|
||||
|
||||
/**
|
||||
* Data decryption
|
||||
*/
|
||||
class Decrypter {
|
||||
public:
|
||||
/**
|
||||
* Decrypt a data block
|
||||
*/
|
||||
static void decrypt(byte *data, size_t size);
|
||||
};
|
||||
|
||||
/**
|
||||
* AdvSys game header
|
||||
*/
|
||||
class Header : public Decrypter {
|
||||
public:
|
||||
bool _valid; ///< Signals whether header is valid
|
||||
size_t _size; ///< Resident size in bytes
|
||||
uint _headerVersion; ///< Header structure version
|
||||
Common::String _name; ///< Adventure name
|
||||
uint _version; ///< Adventure version
|
||||
uint _wordTableOffset; ///< Word table offset
|
||||
uint _wordTypeTableOffset; ///< Word type table offset
|
||||
uint _objectTableOffset; ///< Object table offset
|
||||
uint _actionTableOffset; ///< Action table offset
|
||||
uint _variableTableOffset; ///< Variable table offset
|
||||
uint _dataSpaceOffset; ///< Data space offset
|
||||
uint _codeSpaceOffset; ///< Code space offset
|
||||
uint _dataBlockOffset; ///< First data block offset
|
||||
uint _messageBlockOffset; ///< First message block offset
|
||||
uint _initCodeOffset; ///< Initialization code offset
|
||||
uint _updateCodeOffset; ///< Update code offset
|
||||
uint _beforeOffset; ///< Code offset before verb handler
|
||||
uint _afterOffset; ///< Code offset after verb handler
|
||||
uint _errorHandlerOffset; ///< Error handler code offset
|
||||
uint _saveAreaOffset; ///< Save area offset
|
||||
uint _saveSize; ///< Save area size
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Header() : _valid(false), _size(0), _headerVersion(0), _version(0), _wordTableOffset(0),
|
||||
_wordTypeTableOffset(0), _objectTableOffset(0), _actionTableOffset(0), _variableTableOffset(0),
|
||||
_dataSpaceOffset(0), _codeSpaceOffset(0), _dataBlockOffset(0), _messageBlockOffset(0),
|
||||
_initCodeOffset(0), _updateCodeOffset(0), _beforeOffset(0), _afterOffset(0),
|
||||
_errorHandlerOffset(0), _saveAreaOffset(0), _saveSize(0) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Header(Common::SeekableReadStream *s) {
|
||||
init(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* init the header
|
||||
*/
|
||||
bool init(Common::SeekableReadStream *s);
|
||||
};
|
||||
|
||||
/**
|
||||
* Game abstraction class
|
||||
*/
|
||||
class Game : public Header {
|
||||
struct CacheEntry {
|
||||
int _blockNum;
|
||||
char _data[MESSAGE_BLOCK_SIZE];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
CacheEntry() : _blockNum(-1) {
|
||||
Common::fill(&_data[0], &_data[MESSAGE_BLOCK_SIZE], '\0');
|
||||
}
|
||||
};
|
||||
private:
|
||||
bool _restartFlag;
|
||||
Common::SeekableReadStream *_stream;
|
||||
Common::Array<CacheEntry *> _msgCache;
|
||||
int _msgBlockNum, _msgBlockOffset;
|
||||
private:
|
||||
/**
|
||||
* Find an object property field
|
||||
*/
|
||||
int findProperty(int obj, int prop) const;
|
||||
|
||||
/**
|
||||
* Returns true if an action has a given verb
|
||||
*/
|
||||
bool hasVerb(int act, const Common::Array<int> &verbs) const;
|
||||
|
||||
/**
|
||||
* Returns true if an action is in a given list
|
||||
*/
|
||||
bool hasPreposition(int act, int preposition) const {
|
||||
return inList(getActionField(act, A_PREPOSITIONS), preposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a word is in an element of a given list
|
||||
*/
|
||||
bool inList(int link, int word) const;
|
||||
|
||||
/**
|
||||
* Reads in a message block from the game file
|
||||
*/
|
||||
void readMsgBlock();
|
||||
|
||||
/**
|
||||
* Read the next character for a string
|
||||
*/
|
||||
char readMsgChar();
|
||||
protected:
|
||||
/**
|
||||
* Returns true if an object has a given noun
|
||||
*/
|
||||
bool hasNoun(int obj, int noun) const;
|
||||
|
||||
/**
|
||||
* Returns true if an object has a given adjective
|
||||
*/
|
||||
bool hasAdjective(int obj, int adjective) const;
|
||||
public:
|
||||
Common::Array<byte> _data;
|
||||
int _residentOffset;
|
||||
int _wordCount;
|
||||
int _objectCount;
|
||||
int _actionCount;
|
||||
int _variableCount;
|
||||
|
||||
byte *_wordTable;
|
||||
byte *_wordTypeTable;
|
||||
byte *_objectTable;
|
||||
byte *_actionTable;
|
||||
byte *_variableTable;
|
||||
byte *_saveArea;
|
||||
byte *_dataSpace;
|
||||
byte *_codeSpace;
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Game();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Game();
|
||||
|
||||
/**
|
||||
* init data for the game
|
||||
*/
|
||||
bool init(Common::SeekableReadStream *s);
|
||||
|
||||
/**
|
||||
* Restore savegame data from the game to it's initial state
|
||||
*/
|
||||
void restart();
|
||||
|
||||
/**
|
||||
* Returns true if the game is restarting, and resets the flag
|
||||
*/
|
||||
bool shouldRestart();
|
||||
|
||||
/**
|
||||
* Save the game data to a savegame
|
||||
*/
|
||||
void saveGameData(Common::WriteStream &ws);
|
||||
|
||||
/**
|
||||
* Restore the game data from a savegame
|
||||
*/
|
||||
void loadGameData(Common::ReadStream &rs);
|
||||
|
||||
/**
|
||||
* Find a word in the dictionary
|
||||
*/
|
||||
int findWord(const Common::String &word) const;
|
||||
|
||||
/**
|
||||
* Return a word's type
|
||||
*/
|
||||
WordType getWordType(int word) const {
|
||||
return (WordType)_wordTypeTable[word];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if this is a valid verb
|
||||
*/
|
||||
int checkVerb(const Common::Array<int> &verbs);
|
||||
|
||||
/**
|
||||
* Find an action matching a given description
|
||||
*/
|
||||
int findAction(const Common::Array<int> &verbs, int preposition, int flag);
|
||||
|
||||
/**
|
||||
* Get an object property
|
||||
*/
|
||||
int getObjectProperty(int obj, int prop);
|
||||
|
||||
/**
|
||||
* Sets an object property
|
||||
*/
|
||||
int setObjectProperty(int obj, int prop, int val);
|
||||
|
||||
/**
|
||||
* Gets a field from an object
|
||||
*/
|
||||
int getObjectField(int obj, int offset) const {
|
||||
return READ_LE_UINT16(_dataSpace + getObjectLocation(obj) + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a field in an object
|
||||
*/
|
||||
int setObjectField(int obj, int offset, int val) {
|
||||
WRITE_LE_UINT16(_dataSpace + getObjectLocation(obj) + offset, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a field from an action
|
||||
*/
|
||||
int getActionField(int action, int offset) const {
|
||||
return READ_LE_UINT16(_dataSpace + getActionLocation(action) + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a byte field from an action
|
||||
*/
|
||||
int getActionByte(int action, int offset) const {
|
||||
return _dataSpace[getActionLocation(action) + offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offset of an object from the object table
|
||||
*/
|
||||
int getObjectLocation(int obj) const;
|
||||
|
||||
/**
|
||||
* Gets the offset of an action from the action table
|
||||
*/
|
||||
int getActionLocation(int action) const;
|
||||
|
||||
/**
|
||||
* Get a variable value
|
||||
*/
|
||||
int getVariable(int variableNum);
|
||||
|
||||
/**
|
||||
* Set a variable value
|
||||
*/
|
||||
void setVariable(int variableNum, int value);
|
||||
|
||||
/**
|
||||
* Gets a code byte
|
||||
*/
|
||||
int getCodeByte(int offset) const {
|
||||
return _codeSpace[offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a code byte
|
||||
*/
|
||||
int getCodeWord(int offset) const {
|
||||
return READ_LE_UINT16(_codeSpace + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a word
|
||||
*/
|
||||
int readWord(int offset) const {
|
||||
return READ_LE_UINT16(_dataSpace + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a word
|
||||
*/
|
||||
void writeWord(int offset, int val) {
|
||||
WRITE_LE_UINT16(_dataSpace + offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a string from the messages section
|
||||
*/
|
||||
Common::String readString(int msg);
|
||||
};
|
||||
|
||||
} // End of namespace AdvSys
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user