mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 01:08:25 +00:00
296dd54344
svn-id: r45041
475 lines
14 KiB
C++
475 lines
14 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_SEGMAN_H
|
|
#define SCI_ENGINE_SEGMAN_H
|
|
|
|
#include "common/scummsys.h"
|
|
#include "common/serializer.h"
|
|
#include "sci/engine/vm.h"
|
|
#include "sci/engine/segment.h"
|
|
|
|
namespace Sci {
|
|
|
|
#define GET_SEGMENT(mgr, index, rtype) (((mgr).getSegmentType(index) == (rtype))? (mgr)._heap[index] : NULL)
|
|
|
|
/**
|
|
* Parameters for getScriptSegment().
|
|
*/
|
|
enum ScriptLoadType {
|
|
SCRIPT_GET_DONT_LOAD = 0, /**< Fail if not loaded */
|
|
SCRIPT_GET_LOAD = 1, /**< Load, if neccessary */
|
|
SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */
|
|
};
|
|
|
|
|
|
class SegManager : public Common::Serializable {
|
|
friend class Console;
|
|
public:
|
|
/**
|
|
* Initialize the segment manager.
|
|
*/
|
|
SegManager(ResourceManager *resMan);
|
|
|
|
/**
|
|
* Deallocate all memory associated with the segment manager.
|
|
*/
|
|
~SegManager();
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
// 1. Scripts
|
|
|
|
/**
|
|
* Allocate a script into the segment manager.
|
|
* @param script_nr The number of the script to load
|
|
* @param seg_id The segment ID of the newly allocated segment,
|
|
* on success
|
|
* @return 0 on failure, 1 on success
|
|
*/
|
|
Script *allocateScript(int script_nr, SegmentId *seg_id);
|
|
|
|
// The script must then be initialised; see section (1b.), below.
|
|
|
|
/**
|
|
* Forcefully deallocate a previously allocated script.
|
|
* @param script_nr number of the script to deallocate
|
|
*/
|
|
void deallocateScript(int script_nr);
|
|
|
|
/**
|
|
* Reconstructs scripts. Used when restoring saved games
|
|
*/
|
|
void reconstructScripts(EngineState *s);
|
|
|
|
/**
|
|
* Validate whether the specified public function is exported by
|
|
* the script in the specified segment.
|
|
* @param pubfunct Index of the function to validate
|
|
* @param seg Segment ID of the script the check is to
|
|
* be performed for
|
|
* @return NULL if the public function is invalid, its
|
|
* offset into the script's segment otherwise
|
|
*/
|
|
uint16 validateExportFunc(int pubfunct, SegmentId seg);
|
|
|
|
/**
|
|
* Determines the segment occupied by a certain script, if any.
|
|
* @param script_nr Number of the script to look up
|
|
* @return The script's segment ID, or 0 on failure
|
|
*/
|
|
SegmentId getScriptSegment(int script_nr) const;
|
|
|
|
/**
|
|
* Determines the segment occupied by a certain script. Optionally
|
|
* load it, or load & lock it.
|
|
* @param[in] script_nr Number of the script to look up
|
|
* @param[in] load flag determining whether to load/lock the script
|
|
* @return The script's segment ID, or 0 on failure
|
|
*/
|
|
SegmentId getScriptSegment(int script_nr, ScriptLoadType load);
|
|
|
|
// TODO: document this
|
|
reg_t lookupScriptExport(int script_nr, int export_index) {
|
|
SegmentId seg = getScriptSegment(script_nr, SCRIPT_GET_DONT_LOAD);
|
|
return make_reg(seg, validateExportFunc(export_index, seg));
|
|
}
|
|
|
|
// TODO: document this
|
|
reg_t getClassAddress(int classnr, ScriptLoadType lock, reg_t caller);
|
|
|
|
/**
|
|
* Return a pointer to the specified script.
|
|
* If the id is invalid, does not refer to a script or the script is
|
|
* not loaded, this will invoke error().
|
|
* @param seg ID of the script segment to check for
|
|
* @return A pointer to the Script object
|
|
*/
|
|
Script *getScript(SegmentId seg);
|
|
|
|
|
|
/**
|
|
* Return a pointer to the specified script.
|
|
* If the id is invalid, does not refer to a script, or
|
|
* the script is not loaded, this will return NULL
|
|
* @param seg ID of the script segment to check for
|
|
* @return A pointer to the Script object, or NULL
|
|
*/
|
|
Script *getScriptIfLoaded(SegmentId seg);
|
|
|
|
|
|
// 1b. Script Initialisation
|
|
|
|
// The set of functions below are intended
|
|
// to be used during script instantiation,
|
|
// i.e. loading and linking.
|
|
|
|
/**
|
|
* Initializes a script's local variable block
|
|
* All variables are initialized to zero.
|
|
* @param seg Segment containing the script to initialize
|
|
* @param nr Number of local variables to allocate
|
|
*/
|
|
void scriptInitialiseLocalsZero(SegmentId seg, int nr);
|
|
|
|
/**
|
|
* Initializes a script's local variable block according to a prototype
|
|
* @param location Location to initialize from
|
|
*/
|
|
void scriptInitialiseLocals(reg_t location);
|
|
|
|
/**
|
|
* Tells the segment manager whether exports are wide (32-bit) or not.
|
|
* @param flag true if exports are wide, false otherwise
|
|
*/
|
|
void setExportAreWide(bool flag);
|
|
|
|
// 2. Clones
|
|
|
|
/**
|
|
* Allocate a fresh clone
|
|
* @param addr The offset of the freshly allocated clone
|
|
* @return Reference to the memory allocated for the clone
|
|
*/
|
|
Clone *allocateClone(reg_t *addr);
|
|
|
|
/**
|
|
* Reconstructs clones. Used when restoring saved games
|
|
*/
|
|
void reconstructClones();
|
|
|
|
// 4. Stack
|
|
|
|
/**
|
|
* Allocates a data stack
|
|
* @param size Number of stack entries to reserve
|
|
* @param segid Segment ID of the stack
|
|
* @return The physical stack
|
|
*/
|
|
DataStack *allocateStack(int size, SegmentId *segid);
|
|
|
|
|
|
// 5. System Strings
|
|
|
|
/**
|
|
* Allocates a system string table
|
|
* See also sys_string_acquire();
|
|
* @param[in] segid Segment ID of the stack
|
|
* @returns The physical stack
|
|
*/
|
|
SystemStrings *allocateSysStrings(SegmentId *segid);
|
|
|
|
|
|
// 5. System Strings
|
|
|
|
// 6, 7. Lists and Nodes
|
|
|
|
/**
|
|
* Allocate a fresh list
|
|
* @param[in] addr The offset of the freshly allocated list
|
|
* @return Reference to the memory allocated for the list
|
|
*/
|
|
List *allocateList(reg_t *addr);
|
|
|
|
/**
|
|
* Allocate a fresh node
|
|
* @param[in] addr The offset of the freshly allocated node
|
|
* @return Reference to the memory allocated for the node
|
|
*/
|
|
Node *allocateNode(reg_t *addr);
|
|
|
|
/**
|
|
* Resolves a list pointer to a list.
|
|
* @param addr The address to resolve
|
|
* @return The list referenced, or NULL on error
|
|
*/
|
|
List *lookupList(reg_t addr);
|
|
|
|
/**
|
|
* Resolves an address into a list node.
|
|
* @param addr The address to resolve
|
|
* @return The list node referenced, or NULL on error
|
|
*/
|
|
Node *lookupNode(reg_t addr);
|
|
|
|
|
|
// 8. Hunk Memory
|
|
|
|
/**
|
|
* Allocate a fresh chunk of the hunk
|
|
* @param[in] size Number of bytes to allocate for the hunk entry
|
|
* @param[in] hunk_type A descriptive string for the hunk entry, for
|
|
* debugging purposes
|
|
* @param[out] addr The offset of the freshly allocated hunk entry
|
|
* @return Reference to the memory allocated for the hunk
|
|
* piece
|
|
*/
|
|
Hunk *allocateHunkEntry(const char *hunk_type, int size, reg_t *addr);
|
|
|
|
/**
|
|
* Deallocates a hunk entry
|
|
* @param[in] addr Offset of the hunk entry to delete
|
|
*/
|
|
void freeHunkEntry(reg_t addr);
|
|
|
|
|
|
// 9. Dynamic Memory
|
|
|
|
/**
|
|
* Allocate some dynamic memory
|
|
* @param[in] size Number of bytes to allocate
|
|
* @param[in] description A descriptive string for debugging purposes
|
|
* @param[out] addr The offset of the freshly allocated X
|
|
* @return Raw pointer into the allocated dynamic
|
|
* memory
|
|
*/
|
|
byte *allocDynmem(int size, const char *description, reg_t *addr);
|
|
|
|
/**
|
|
* Deallocates a piece of dynamic memory
|
|
* @param[in] addr Offset of the dynmem chunk to free
|
|
*/
|
|
int freeDynmem(reg_t addr);
|
|
|
|
|
|
// Generic Operations on Segments and Addresses
|
|
|
|
/**
|
|
* Dereferences a raw memory pointer
|
|
* @param[in] reg The reference to dereference
|
|
* @return The data block referenced
|
|
*/
|
|
SegmentRef dereference(reg_t pointer);
|
|
|
|
/**
|
|
* Dereferences a heap pointer pointing to raw memory.
|
|
* @param pointer The pointer to dereference
|
|
* @parm entries The number of values expected (for checkingO
|
|
* @return A physical reference to the address pointed to, or NULL on error or
|
|
* if not enough entries were available.
|
|
*/
|
|
byte *derefBulkPtr(reg_t pointer, int entries);
|
|
|
|
/**
|
|
* Dereferences a heap pointer pointing to a (list of) register(s).
|
|
* Ensures alignedness of data.
|
|
* @param pointer The pointer to dereference
|
|
* @parm entries The number of values expected (for checking)
|
|
* @return A physical reference to the address pointed to, or NULL on error or
|
|
* if not enough entries were available.
|
|
*/
|
|
reg_t *derefRegPtr(reg_t pointer, int entries);
|
|
|
|
/**
|
|
* Dereferences a heap pointer pointing to raw memory.
|
|
* @param pointer The pointer to dereference
|
|
* @parm entries The number of values expected (for checking)
|
|
* @return A physical reference to the address pointed to, or NULL on error or
|
|
* if not enough entries were available.
|
|
*/
|
|
char *derefString(reg_t pointer, int entries = 0);
|
|
|
|
/**
|
|
* Return the string referenced by pointer.
|
|
* pointer can point to either a raw or non-raw segment.
|
|
* @param pointer The pointer to dereference
|
|
* @parm entries The number of values expected (for checking)
|
|
* @return The string referenced, or an empty string if not enough
|
|
* entries were available.
|
|
*/
|
|
Common::String getString(reg_t pointer, int entries = 0);
|
|
|
|
|
|
/**
|
|
* Copies a string from src to dest.
|
|
* src and dest can point to raw and non-raw segments.
|
|
* Conversion is performed as required.
|
|
*/
|
|
void strcpy(reg_t dest, reg_t src);
|
|
|
|
/**
|
|
* Copies a string from src to dest.
|
|
* dest can point to a raw or non-raw segment.
|
|
* Conversion is performed as required.
|
|
*/
|
|
void strcpy(reg_t dest, const char *src);
|
|
|
|
/**
|
|
* Copies a string from src to dest.
|
|
* src and dest can point to raw and non-raw segments.
|
|
* Conversion is performed as required. At most n characters are copied.
|
|
* TODO: determine if dest should always be null-terminated.
|
|
*/
|
|
void strncpy(reg_t dest, reg_t src, size_t n);
|
|
|
|
/**
|
|
* Copies a string from src to dest.
|
|
* dest can point to a raw or non-raw segment.
|
|
* Conversion is performed as required. At most n characters are copied.
|
|
* TODO: determine if dest should always be null-terminated.
|
|
*/
|
|
void strncpy(reg_t dest, const char *src, size_t n);
|
|
|
|
/**
|
|
* Copies n bytes of data from src to dest.
|
|
* src and dest can point to raw and non-raw segments.
|
|
* Conversion is performed as required.
|
|
*/
|
|
void memcpy(reg_t dest, reg_t src, size_t n);
|
|
|
|
/**
|
|
* Copies n bytes of data from src to dest.
|
|
* dest can point to a raw or non-raw segment.
|
|
* Conversion is performed as required.
|
|
*/
|
|
void memcpy(reg_t dest, const byte* src, size_t n);
|
|
|
|
/**
|
|
* Copies n bytes of data from src to dest.
|
|
* src can point to raw and non-raw segments.
|
|
* Conversion is performed as required.
|
|
*/
|
|
void memcpy(byte *dest, reg_t src, size_t n);
|
|
|
|
/**
|
|
* Determine length of string at str.
|
|
* str can point to a raw or non-raw segment.
|
|
*/
|
|
size_t strlen(reg_t str);
|
|
|
|
/**
|
|
* Finds a unique segment by type
|
|
* @param type The type of the segment to find
|
|
* @return The segment number, or -1 if the segment wasn't found
|
|
*/
|
|
SegmentId findSegmentByType(int type);
|
|
|
|
// TODO: document this
|
|
SegmentObj *getSegmentObj(SegmentId seg);
|
|
|
|
// TODO: document this
|
|
SegmentType getSegmentType(SegmentId seg);
|
|
|
|
/**
|
|
* Retrieves an object from the specified location
|
|
* @param[in] offset Location (segment, offset) of the object
|
|
* @return The object in question, or NULL if there is none
|
|
*/
|
|
Object *getObject(reg_t pos);
|
|
|
|
/**
|
|
* Checks whether a heap address contains an object
|
|
* @parm obj The address to check
|
|
* @return True if it is an object, false otherwise
|
|
*/
|
|
bool isObject(reg_t obj) { return getObject(obj) != NULL; }
|
|
|
|
// TODO: document this
|
|
bool isHeapObject(reg_t pos);
|
|
|
|
/**
|
|
* Determines the name of an object
|
|
* @param[in] pos Location (segment, offset) of the object
|
|
* @return A name for that object, or a string describing an error
|
|
* that occured while looking it up. The string is stored
|
|
* in a static buffer and need not be freed (neither may
|
|
* it be modified).
|
|
*/
|
|
const char *getObjectName(reg_t pos);
|
|
|
|
/**
|
|
* Find the address of an object by its name. In case multiple objects
|
|
* with the same name occur, the optional index parameter can be used
|
|
* to distinguish between them. If index is -1, then if there is a
|
|
* unique object with the specified name, its address is returned;
|
|
* if there are multiple matches, or none, then NULL_REG is returned.
|
|
*
|
|
* @param name the name of the object we are looking for
|
|
* @param index the index of the object in case there are multiple
|
|
* @return the address of the object, or NULL_REG
|
|
*/
|
|
reg_t findObjectByName(const Common::String &name, int index = -1);
|
|
|
|
void scriptRelocateExportsSci11(SegmentId seg);
|
|
void scriptInitialiseObjectsSci11(SegmentId seg);
|
|
|
|
public: // TODO: make private
|
|
Common::Array<SegmentObj *> _heap;
|
|
Common::Array<Class> _classtable; /**< Table of all classes */
|
|
|
|
private:
|
|
/** Map script ids to segment ids. */
|
|
Common::HashMap<int, SegmentId> _scriptSegMap;
|
|
|
|
ResourceManager *_resMan;
|
|
|
|
bool _exportsAreWide;
|
|
|
|
SegmentId Clones_seg_id; ///< ID of the (a) clones segment
|
|
SegmentId Lists_seg_id; ///< ID of the (a) list segment
|
|
SegmentId Nodes_seg_id; ///< ID of the (a) node segment
|
|
SegmentId Hunks_seg_id; ///< ID of the (a) hunk segment
|
|
|
|
private:
|
|
SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid);
|
|
LocalVariables *allocLocalsSegment(Script *scr, int count);
|
|
int deallocate(SegmentId seg, bool recursive);
|
|
int createClassTable();
|
|
|
|
SegmentId findFreeSegment() const;
|
|
|
|
/**
|
|
* Check segment validity
|
|
* @param[in] seg The segment to validate
|
|
* @return false if 'seg' is an invalid segment, true if
|
|
* 'seg' is a valid segment
|
|
*/
|
|
bool check(SegmentId seg);
|
|
};
|
|
|
|
} // End of namespace Sci
|
|
|
|
#endif // SCI_ENGINE_SEGMAN
|