mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-23 10:19:27 +00:00
7a14846bdd
svn-id: r50358
242 lines
8.4 KiB
C++
242 lines
8.4 KiB
C++
/* 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.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#ifndef SCI_ENGINE_VM_H
|
|
#define SCI_ENGINE_VM_H
|
|
|
|
/* VM and kernel declarations */
|
|
|
|
#include "sci/engine/vm_types.h" // for reg_t
|
|
#include "sci/resource.h" // for SciVersion
|
|
|
|
#include "common/util.h"
|
|
|
|
namespace Sci {
|
|
|
|
class SegManager;
|
|
struct EngineState;
|
|
class Object;
|
|
class ResourceManager;
|
|
|
|
/** Number of bytes to be allocated for the stack */
|
|
#define VM_STACK_SIZE 0x1000
|
|
|
|
/** Magical object identifier */
|
|
#define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234
|
|
|
|
/** Offset of this identifier */
|
|
#define SCRIPT_OBJECT_MAGIC_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? -8 : 0)
|
|
|
|
/** Stack pointer value: Use predecessor's value */
|
|
#define CALL_SP_CARRY NULL
|
|
|
|
/** Types of selectors as returned by lookupSelector() below. */
|
|
enum SelectorType {
|
|
kSelectorNone = 0,
|
|
kSelectorVariable,
|
|
kSelectorMethod
|
|
};
|
|
|
|
struct Class {
|
|
int script; ///< number of the script the class is in, -1 for non-existing
|
|
reg_t reg; ///< offset; script-relative offset, segment: 0 if not instantiated
|
|
};
|
|
|
|
#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER)
|
|
|
|
// A reference to an object's variable.
|
|
// The object is stored as a reg_t, the variable as an index into _variables
|
|
struct ObjVarRef {
|
|
reg_t obj;
|
|
int varindex;
|
|
|
|
reg_t* getPointer(SegManager *segMan) const;
|
|
};
|
|
|
|
enum ExecStackType {
|
|
EXEC_STACK_TYPE_CALL = 0,
|
|
EXEC_STACK_TYPE_KERNEL = 1,
|
|
EXEC_STACK_TYPE_VARSELECTOR = 2
|
|
};
|
|
|
|
struct ExecStack {
|
|
reg_t objp; ///< Pointer to the beginning of the current object
|
|
reg_t sendp; ///< Pointer to the object containing the invoked method
|
|
|
|
union {
|
|
ObjVarRef varp; // Variable pointer for r/w access
|
|
reg_t pc; // Pointer to the initial program counter. Not accurate for the TOS element
|
|
} addr;
|
|
|
|
StackPtr fp; // Frame pointer
|
|
StackPtr sp; // Stack pointer
|
|
int argc;
|
|
|
|
StackPtr variables_argp; // Argument pointer
|
|
SegmentId local_segment; // local variables etc
|
|
|
|
Selector selector; // The selector which was used to call or -1 if not applicable
|
|
int exportId; // The exportId which was called or -1 if not applicable
|
|
int localCallOffset; // Local call offset or -1 if not applicable
|
|
int origin; // The stack frame position the call was made from, or -1 if it was the initial call
|
|
ExecStackType type;
|
|
|
|
reg_t* getVarPointer(SegManager *segMan) const;
|
|
};
|
|
|
|
enum {
|
|
VAR_GLOBAL = 0,
|
|
VAR_LOCAL = 1,
|
|
VAR_TEMP = 2,
|
|
VAR_PARAM = 3
|
|
};
|
|
|
|
/** Number of kernel calls in between gcs; should be < 50000 */
|
|
enum {
|
|
GC_INTERVAL = 32768
|
|
};
|
|
|
|
|
|
/**
|
|
* Executes function pubfunct of the specified script.
|
|
* @param[in] s The state which is to be executed with
|
|
* @param[in] script The script which is called
|
|
* @param[in] pubfunct The exported script function which is to
|
|
* be called
|
|
* @param[in] sp Stack pointer position
|
|
* @param[in] calling_obj The heap address of the object that
|
|
* executed the call
|
|
* @param[in] argc Number of arguments supplied
|
|
* @param[in] argp Pointer to the first supplied argument
|
|
* @return A pointer to the new exec stack TOS entry
|
|
*/
|
|
ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct,
|
|
StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp);
|
|
|
|
|
|
/**
|
|
* Executes a "send" or related operation to a selector.
|
|
* @param[in] s The EngineState to operate on
|
|
* @param[in] send_obj Heap address of the object to send to
|
|
* @param[in] work_obj Heap address of the object initiating the send
|
|
* @param[in] sp Stack pointer position
|
|
* @param[in] framesize Size of the send as determined by the "send"
|
|
* operation
|
|
* @param[in] argp Pointer to the beginning of the heap block
|
|
* containing the data to be sent. This area is a
|
|
* succession of one or more sequences of
|
|
* [selector_number][argument_counter] and then
|
|
* "argument_counter" word entries with the
|
|
* parameter values.
|
|
* @return A pointer to the new execution stack TOS entry
|
|
*/
|
|
ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj,
|
|
StackPtr sp, int framesize, StackPtr argp);
|
|
|
|
|
|
/**
|
|
* This function executes SCI bytecode
|
|
* It executes the code on s->heap[pc] until it hits a 'ret' operation
|
|
* while (stack_base == stack_pos). Requires s to be set up correctly.
|
|
* @param[in] s The state to use
|
|
* @param[in] restoring true if s has just been restored, false otherwise
|
|
*/
|
|
void run_vm(EngineState *s, bool restoring);
|
|
|
|
/**
|
|
* Debugger functionality
|
|
* @param[in] s The state at which debugging should take place
|
|
*/
|
|
void script_debug(EngineState *s);
|
|
|
|
/**
|
|
* Looks up a selector and returns its type and value
|
|
* varindex is written to iff it is non-NULL and the selector indicates a property of the object.
|
|
* @param[in] segMan The Segment Manager
|
|
* @param[in] obj Address of the object to look the selector up in
|
|
* @param[in] selectorid The selector to look up
|
|
* @param[out] varp A reference to the selector, if it is a
|
|
* variable.
|
|
* @param[out] fptr A reference to the function described by that
|
|
* selector, if it is a valid function selector.
|
|
* fptr is written to iff it is non-NULL and the
|
|
* selector indicates a member function of that
|
|
* object.
|
|
* @return kSelectorNone if the selector was not found in
|
|
* the object or its superclasses.
|
|
* kSelectorVariable if the selector represents an
|
|
* object-relative variable.
|
|
* kSelectorMethod if the selector represents a
|
|
* method
|
|
*/
|
|
SelectorType lookupSelector(SegManager *segMan, reg_t obj, Selector selectorid,
|
|
ObjVarRef *varp, reg_t *fptr);
|
|
|
|
/**
|
|
* Makes sure that a script and its superclasses get loaded to the heap.
|
|
* If the script already has been loaded, only the number of lockers is
|
|
* increased. All scripts containing superclasses of this script are loaded
|
|
* recursively as well, unless 'recursive' is set to zero. The
|
|
* complementary function is "script_uninstantiate()" below.
|
|
* @param[in] resMan The resource manager
|
|
* @param[in] segMan The segment manager
|
|
* @param[in] script_nr The script number to load
|
|
* @return The script's segment ID or 0 if out of heap
|
|
*/
|
|
int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr);
|
|
|
|
/**
|
|
* Decreases the numer of lockers of a script and unloads it if that number
|
|
* reaches zero.
|
|
* This function will recursively unload scripts containing its
|
|
* superclasses, if those aren't locked by other scripts as well.
|
|
* @param[in] segMan The segment manager
|
|
* @param[in] version The SCI version to use
|
|
* @param[in] script_nr The script number that is requestet to be unloaded
|
|
*/
|
|
void script_uninstantiate(SegManager *segMan, int script_nr);
|
|
|
|
/**
|
|
* Read a PMachine instruction from a memory buffer and return its length.
|
|
*
|
|
* @param[in] src address from which to start parsing
|
|
* @param[out] extOpcode "extended" opcode of the parsed instruction
|
|
* @param[out] opparams parameter for the parsed instruction
|
|
* @return the length in bytes of the instruction
|
|
*
|
|
* @todo How about changing opparams from int16 to int / int32 to preserve
|
|
* unsigned 16bit words as read for Script_Word? In the past, this
|
|
* was irrelevant as only a debug opcode used Script_Word. But with
|
|
* SCI32 we are now using Script_Word for more opcodes. Maybe this is
|
|
* just a mistake and those opcodes should used Script_SWord -- but if
|
|
* not then we definitely should change this to int, else we might run
|
|
* into trouble if we encounter high value words. *If* those exist at all.
|
|
*/
|
|
int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]);
|
|
|
|
} // End of namespace Sci
|
|
|
|
#endif // SCI_ENGINE_VM_H
|