Initial commit
This commit is contained in:
150
engines/wintermute/base/scriptables/dcscript.h
Normal file
150
engines/wintermute/base/scriptables/dcscript.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_DCSCRIPT_H
|
||||
#define WINTERMUTE_DCSCRIPT_H
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
#define SCRIPT_MAGIC 0xDEC0ADDE
|
||||
#define SCRIPT_VERSION 0x0102
|
||||
|
||||
// value types
|
||||
typedef enum {
|
||||
VAL_NULL,
|
||||
VAL_STRING,
|
||||
VAL_INT,
|
||||
VAL_BOOL,
|
||||
VAL_FLOAT,
|
||||
VAL_OBJECT,
|
||||
VAL_NATIVE,
|
||||
VAL_VARIABLE_REF
|
||||
} TValType;
|
||||
|
||||
|
||||
// script states
|
||||
typedef enum {
|
||||
SCRIPT_RUNNING,
|
||||
SCRIPT_WAITING,
|
||||
SCRIPT_SLEEPING,
|
||||
SCRIPT_FINISHED,
|
||||
SCRIPT_PERSISTENT,
|
||||
SCRIPT_ERROR,
|
||||
SCRIPT_PAUSED,
|
||||
SCRIPT_WAITING_SCRIPT,
|
||||
SCRIPT_THREAD_FINISHED
|
||||
} TScriptState;
|
||||
|
||||
// opcodes
|
||||
typedef enum {
|
||||
II_DEF_VAR = 0,
|
||||
II_DEF_GLOB_VAR,
|
||||
II_RET,
|
||||
II_RET_EVENT,
|
||||
II_CALL,
|
||||
II_CALL_BY_EXP,
|
||||
II_EXTERNAL_CALL,
|
||||
II_SCOPE,
|
||||
II_CORRECT_STACK,
|
||||
II_CREATE_OBJECT,
|
||||
II_POP_EMPTY,
|
||||
II_PUSH_VAR,
|
||||
II_PUSH_VAR_REF,
|
||||
II_POP_VAR,
|
||||
II_PUSH_VAR_THIS, // push current this on stack
|
||||
II_PUSH_INT,
|
||||
II_PUSH_BOOL,
|
||||
II_PUSH_FLOAT,
|
||||
II_PUSH_STRING,
|
||||
II_PUSH_NULL,
|
||||
II_PUSH_THIS_FROM_STACK,
|
||||
II_PUSH_THIS,
|
||||
II_POP_THIS,
|
||||
II_PUSH_BY_EXP,
|
||||
II_POP_BY_EXP,
|
||||
II_JMP,
|
||||
II_JMP_FALSE,
|
||||
II_ADD,
|
||||
II_SUB,
|
||||
II_MUL,
|
||||
II_DIV,
|
||||
II_MODULO,
|
||||
II_NOT,
|
||||
II_AND,
|
||||
II_OR,
|
||||
II_CMP_EQ,
|
||||
II_CMP_NE,
|
||||
II_CMP_L,
|
||||
II_CMP_G,
|
||||
II_CMP_LE,
|
||||
II_CMP_GE,
|
||||
II_CMP_STRICT_EQ,
|
||||
II_CMP_STRICT_NE,
|
||||
II_DBG_LINE,
|
||||
II_POP_REG1,
|
||||
II_PUSH_REG1,
|
||||
II_DEF_CONST_VAR
|
||||
} TInstruction;
|
||||
|
||||
// operation code types
|
||||
typedef enum {
|
||||
OPCODES_UNCHANGED = 0
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
,
|
||||
OPCODES_FOXTAIL_1_2_896,
|
||||
OPCODES_FOXTAIL_1_2_902
|
||||
#endif
|
||||
} TOpcodesType;
|
||||
|
||||
// external data types
|
||||
typedef enum {
|
||||
TYPE_VOID = 0,
|
||||
TYPE_BOOL,
|
||||
TYPE_LONG,
|
||||
TYPE_BYTE,
|
||||
TYPE_STRING,
|
||||
TYPE_FLOAT,
|
||||
TYPE_DOUBLE,
|
||||
TYPE_MEMBUFFER
|
||||
} TExternalType;
|
||||
|
||||
|
||||
// call types
|
||||
typedef enum {
|
||||
CALL_STDCALL = 0,
|
||||
CALL_CDECL,
|
||||
CALL_THISCALL
|
||||
} TCallType;
|
||||
|
||||
// element types
|
||||
typedef enum {
|
||||
ELEMENT_STRING = 0
|
||||
} TElementType;
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,147 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/tokenizer.h"
|
||||
#include "debuggable_script.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/debuggable/debuggable_script_engine.h"
|
||||
#include "engines/wintermute/debugger/breakpoint.h"
|
||||
#include "engines/wintermute/debugger/script_monitor.h"
|
||||
#include "engines/wintermute/debugger/watch_instance.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
DebuggableScript::DebuggableScript(BaseGame *inGame, DebuggableScEngine *engine) : ScScript(inGame, engine), _engine(engine), _stepDepth(kDefaultStepDepth) {
|
||||
_engine->_watches.subscribe(this);
|
||||
for (uint i = 0; i < _engine->_watches.size(); i++) {
|
||||
_watchInstances.add(new WatchInstance(_engine->_watches[i], this));
|
||||
}
|
||||
}
|
||||
|
||||
DebuggableScript::~DebuggableScript() {
|
||||
for (int32 i = 0; i < _watchInstances.getSize(); i++) {
|
||||
delete _watchInstances[i];
|
||||
}
|
||||
_engine->_watches.unsubscribe(this);
|
||||
}
|
||||
void DebuggableScript::preInstHook(uint32 inst) {}
|
||||
|
||||
void DebuggableScript::postInstHook(uint32 inst) {
|
||||
if (inst == II_DBG_LINE) {
|
||||
for (uint j = 0; j < _engine->_breakpoints.size(); j++) {
|
||||
_engine->_breakpoints[j]->evaluate(this);
|
||||
}
|
||||
|
||||
if (_callStack->_sP <= _stepDepth) {
|
||||
_engine->_monitor->notifyStep(this);
|
||||
}
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < _watchInstances.getSize(); i++) {
|
||||
this->_watchInstances[i]->evaluate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DebuggableScript::setStepDepth(int depth) {
|
||||
_stepDepth = depth;
|
||||
}
|
||||
|
||||
void DebuggableScript::step() {
|
||||
setStepDepth(_callStack->_sP);
|
||||
// TODO double check
|
||||
}
|
||||
|
||||
void DebuggableScript::stepContinue() {
|
||||
setStepDepth(kDefaultStepDepth);
|
||||
}
|
||||
|
||||
void DebuggableScript::stepFinish() {
|
||||
setStepDepth(_callStack->_sP - 1);
|
||||
}
|
||||
|
||||
ScValue *DebuggableScript::resolveName(const Common::String &name) {
|
||||
|
||||
Common::String trimmed = name;
|
||||
trimmed.trim();
|
||||
Common::StringTokenizer st = Common::StringTokenizer(trimmed.c_str(), ".");
|
||||
Common::String nextToken;
|
||||
|
||||
nextToken = st.nextToken();
|
||||
|
||||
|
||||
char cstr[256]; // TODO not pretty
|
||||
Common::strlcpy(cstr, nextToken.c_str(), nextToken.size() + 1);
|
||||
cstr[255] = '\0'; // We 0-terminate it just in case it's > 256 chars.
|
||||
|
||||
ScValue *value = getVar(cstr);
|
||||
ScValue *res = new ScValue(_game);
|
||||
|
||||
if (value == nullptr) {
|
||||
return res;
|
||||
}
|
||||
|
||||
nextToken = st.nextToken();
|
||||
|
||||
while (nextToken.size() > 0 && (value->isObject() || value->isNative())) {
|
||||
value = value->getProp(nextToken.c_str());
|
||||
nextToken = st.nextToken();
|
||||
if (value == nullptr) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
res->copy(value);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint DebuggableScript::dbgGetLine() const {
|
||||
return _currentLine;
|
||||
}
|
||||
|
||||
Common::String DebuggableScript::dbgGetFilename() const {
|
||||
return _filename;
|
||||
}
|
||||
|
||||
void DebuggableScript::updateWatches() {
|
||||
// We drop obsolete watches
|
||||
for (int32 i = 0; i < _watchInstances.getSize(); i++) {
|
||||
Watch *findMe = _watchInstances[i]->_watch;
|
||||
if (Common::find(_engine->_watches.begin(), _engine->_watches.end(), findMe) == _engine->_watches.end()) {
|
||||
// Not found on engine-wide list, must have been removed from watches. Must remove it from local list.
|
||||
delete _watchInstances[i];
|
||||
_watchInstances.removeAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
// We add any new watches
|
||||
for (uint i = 0; i < _engine->_watches.size(); i++) {
|
||||
Watch *findMe = _engine->_watches[i];
|
||||
if (Common::find(_engine->_watches.begin(), _engine->_watches.end(), findMe) == _engine->_watches.end()) {
|
||||
// Not found on local list, must be a new one.
|
||||
_watchInstances.add(new WatchInstance(_engine->_watches[i], this));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End of namespace Wintermute
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/* 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 DEBUGGABLE_SCRIPT_H_
|
||||
#define DEBUGGABLE_SCRIPT_H_
|
||||
#include "engines/wintermute/base/scriptables/script.h"
|
||||
|
||||
namespace Wintermute {
|
||||
class ScriptMonitor;
|
||||
class Watch;
|
||||
class WatchInstance;
|
||||
class DebuggableScEngine;
|
||||
|
||||
class DebuggableScript : public ScScript {
|
||||
static const int kDefaultStepDepth = -2;
|
||||
int32 _stepDepth;
|
||||
DebuggableScEngine *_engine;
|
||||
BaseArray<WatchInstance *> _watchInstances;
|
||||
void preInstHook(uint32 inst) override;
|
||||
void postInstHook(uint32 inst) override;
|
||||
void setStepDepth(int depth);
|
||||
public:
|
||||
DebuggableScript(BaseGame *inGame, DebuggableScEngine *engine);
|
||||
~DebuggableScript() override;
|
||||
ScValue *resolveName(const Common::String &name);
|
||||
/**
|
||||
* Return argument to last II_DBG_LINE encountered
|
||||
*/
|
||||
virtual uint dbgGetLine() const;
|
||||
virtual Common::String dbgGetFilename() const;
|
||||
/**
|
||||
* Execute one more instruction
|
||||
*/
|
||||
void step();
|
||||
/**
|
||||
* Continue execution
|
||||
*/
|
||||
void stepContinue();
|
||||
/**
|
||||
* Continue execution until the activation record on top of the stack is popped
|
||||
*/
|
||||
void stepFinish();
|
||||
void updateWatches();
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif /* DEBUGGABLE_SCRIPT_H_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "debuggable_script_engine.h"
|
||||
#include "debuggable_script.h"
|
||||
#include "engines/wintermute/debugger/watch_instance.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
DebuggableScEngine::DebuggableScEngine(BaseGame *inGame) : ScEngine(inGame), _monitor(nullptr) {}
|
||||
|
||||
void DebuggableScEngine::attachMonitor(ScriptMonitor *monitor) {
|
||||
_monitor = monitor;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
@@ -0,0 +1,109 @@
|
||||
/* 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 DEBUGGABLE_SCRIPT_ENGINE_H_
|
||||
#define DEBUGGABLE_SCRIPT_ENGINE_H_
|
||||
#include "engines/wintermute/base/scriptables/script_engine.h"
|
||||
#include "engines/wintermute/coll_templ.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "engines/wintermute/base/scriptables/debuggable/debuggable_script.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class Breakpoint;
|
||||
class Watch;
|
||||
class DebuggableScript;
|
||||
class DebuggableScEngine;
|
||||
class ScriptMonitor;
|
||||
|
||||
class PublisherWArray : private Common::Array<Watch *> {
|
||||
Common::Array<DebuggableScript *> _subscribers;
|
||||
void notifySubscribers() {
|
||||
for (uint i = 0; i < _subscribers.size(); i++) {
|
||||
_subscribers[i]->updateWatches();
|
||||
}
|
||||
}
|
||||
public:
|
||||
void subscribe(DebuggableScript *script) {
|
||||
if (Common::find(_subscribers.begin(), _subscribers.end(), script) == _subscribers.end()) {
|
||||
// If not already contained
|
||||
_subscribers.push_back(script);
|
||||
}
|
||||
}
|
||||
|
||||
void unsubscribe(DebuggableScript *script) {
|
||||
int location = -1;
|
||||
for (uint i = 0; i < _subscribers.size() && location == -1; i++) {
|
||||
if (_subscribers[i] == script) {
|
||||
location = i;
|
||||
}
|
||||
}
|
||||
if (location >= 0) {
|
||||
_subscribers.remove_at(location);
|
||||
} else {
|
||||
// TODO: If this happens... it's funny. Some script out there forgot to subscribe.
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(Watch *newElement) {
|
||||
Common::Array<Watch *>::push_back(newElement);
|
||||
notifySubscribers();
|
||||
}
|
||||
|
||||
size_type size() {
|
||||
return Common::Array<Watch *>::size();
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return Common::Array<Watch *>::begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return Common::Array<Watch *>::end();
|
||||
}
|
||||
|
||||
Watch *&operator[](size_type idx) {
|
||||
return Common::Array<Watch *>::operator[](idx);
|
||||
}
|
||||
Watch *remove_at(size_type idx) {
|
||||
Watch *res = Common::Array<Watch *>::remove_at(idx);
|
||||
notifySubscribers();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
class DebuggableScEngine : public ScEngine {
|
||||
Common::Array<Breakpoint *> _breakpoints;
|
||||
PublisherWArray _watches;
|
||||
ScriptMonitor *_monitor;
|
||||
public:
|
||||
DebuggableScEngine(BaseGame *inGame);
|
||||
void attachMonitor(ScriptMonitor *);
|
||||
|
||||
friend class DebuggerController;
|
||||
friend class DebuggableScript;
|
||||
friend class ScScript;
|
||||
friend class WatchableScriptArray;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif /* DEBUGGABLE_SCRIPT_ENGINE_H_ */
|
||||
1534
engines/wintermute/base/scriptables/script.cpp
Normal file
1534
engines/wintermute/base/scriptables/script.cpp
Normal file
File diff suppressed because it is too large
Load Diff
178
engines/wintermute/base/scriptables/script.h
Normal file
178
engines/wintermute/base/scriptables/script.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SCSCRIPT_H
|
||||
#define WINTERMUTE_SCSCRIPT_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base.h"
|
||||
#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView
|
||||
#include "engines/wintermute/coll_templ.h"
|
||||
#include "engines/wintermute/persistent.h"
|
||||
|
||||
namespace Wintermute {
|
||||
class BaseScriptHolder;
|
||||
class BaseObject;
|
||||
class ScEngine;
|
||||
class ScStack;
|
||||
class ScValue;
|
||||
|
||||
class ScScript : public BaseClass {
|
||||
public:
|
||||
BaseArray<int> _breakpoints;
|
||||
bool _tracingMode;
|
||||
|
||||
ScScript *_parentScript;
|
||||
bool _unbreakable;
|
||||
bool finishThreads();
|
||||
bool copyParameters(ScStack *stack);
|
||||
|
||||
void afterLoad();
|
||||
|
||||
ScValue *_operand;
|
||||
ScValue *_reg1;
|
||||
bool _freezable;
|
||||
bool resume();
|
||||
bool pause();
|
||||
bool canHandleEvent(const char *eventName);
|
||||
bool canHandleMethod(const char *methodName);
|
||||
bool createThread(ScScript *original, uint32 initIP, const char *eventName);
|
||||
bool createMethodThread(ScScript *original, const char *methodName);
|
||||
ScScript *invokeEventHandler(const char *eventName, bool unbreakable = false);
|
||||
uint32 _timeSlice;
|
||||
DECLARE_PERSISTENT(ScScript, BaseClass)
|
||||
void runtimeError(const char *fmt, ...);
|
||||
bool run();
|
||||
bool finish(bool includingThreads = false);
|
||||
bool sleep(uint32 duration);
|
||||
bool waitForExclusive(BaseObject *object);
|
||||
bool waitFor(BaseObject *object);
|
||||
uint32 _waitTime;
|
||||
bool _waitFrozen;
|
||||
BaseObject *_waitObject;
|
||||
ScScript *_waitScript;
|
||||
TScriptState _state;
|
||||
TScriptState _origState;
|
||||
ScValue *getVar(char *name);
|
||||
uint32 getFuncPos(const char *name);
|
||||
uint32 getEventPos(const char *name);
|
||||
uint32 getMethodPos(const char *name);
|
||||
typedef struct {
|
||||
uint32 magic;
|
||||
uint32 version;
|
||||
uint32 codeStart;
|
||||
uint32 funcTable;
|
||||
uint32 symbolTable;
|
||||
uint32 eventTable;
|
||||
uint32 externalsTable;
|
||||
uint32 methodTable;
|
||||
} TScriptHeader;
|
||||
|
||||
TScriptHeader _header{};
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
uint32 pos;
|
||||
} TFunctionPos;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
uint32 pos;
|
||||
} TMethodPos;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
uint32 pos;
|
||||
} TEventPos;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *dll_name;
|
||||
TCallType call_type;
|
||||
TExternalType returns;
|
||||
int32 numParams;
|
||||
TExternalType *params;
|
||||
} TExternalFunction;
|
||||
|
||||
|
||||
ScStack *_callStack;
|
||||
ScStack *_thisStack;
|
||||
ScStack *_scopeStack;
|
||||
ScStack *_stack;
|
||||
ScValue *_globals;
|
||||
ScEngine *_engine;
|
||||
int32 _currentLine;
|
||||
virtual bool executeInstruction();
|
||||
char *getString();
|
||||
uint32 getDWORD();
|
||||
double getFloat();
|
||||
void cleanup();
|
||||
bool create(const char *filename, byte *buffer, uint32 size, BaseScriptHolder *owner);
|
||||
uint32 _iP;
|
||||
void readHeader();
|
||||
uint32 _bufferSize;
|
||||
byte *_buffer;
|
||||
Common::SeekableReadStream *_scriptStream;
|
||||
ScScript(BaseGame *inGame, ScEngine *engine);
|
||||
~ScScript() override;
|
||||
char *_filename;
|
||||
char **_symbols;
|
||||
uint32 _numSymbols;
|
||||
TFunctionPos *_functions;
|
||||
TMethodPos *_methods;
|
||||
TEventPos *_events;
|
||||
uint32 _numExternals;
|
||||
TExternalFunction *_externals;
|
||||
uint32 _numFunctions;
|
||||
uint32 _numMethods;
|
||||
uint32 _numEvents;
|
||||
bool _thread;
|
||||
bool _methodThread;
|
||||
char *_threadEvent;
|
||||
BaseScriptHolder *_owner;
|
||||
ScScript::TExternalFunction *getExternal(char *name);
|
||||
bool externalCall(ScStack *stack, ScStack *thisStack, ScScript::TExternalFunction *function);
|
||||
private:
|
||||
|
||||
bool initScript();
|
||||
bool initTables();
|
||||
|
||||
virtual void preInstHook(uint32 inst);
|
||||
virtual void postInstHook(uint32 inst);
|
||||
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
TOpcodesType _opcodesType;
|
||||
void initOpcodesType();
|
||||
uint32 decodeAltOpcodes(uint32 inst);
|
||||
#endif
|
||||
|
||||
bool _enableFloatCompareWA{};
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
644
engines/wintermute/base/scriptables/script_engine.cpp
Normal file
644
engines/wintermute/base/scriptables/script_engine.cpp
Normal file
@@ -0,0 +1,644 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/scriptables/script_engine.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/utils/utils.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(ScEngine, true)
|
||||
|
||||
#define COMPILER_DLL "dcscomp.dll"
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScEngine::ScEngine(BaseGame *inGame) : BaseClass(inGame) {
|
||||
_game->LOG(0, "Initializing scripting engine...");
|
||||
|
||||
if (_compilerAvailable) {
|
||||
_game->LOG(0, " Script compiler bound successfuly");
|
||||
} else {
|
||||
_game->LOG(0, " Script compiler is NOT available");
|
||||
}
|
||||
|
||||
_globals = new ScValue(_game);
|
||||
|
||||
|
||||
// register 'Game' as global variable
|
||||
if (!_globals->propExists("Game")) {
|
||||
ScValue val(_game);
|
||||
val.setNative(_game, true);
|
||||
_globals->setProp("Game", &val);
|
||||
}
|
||||
|
||||
// register 'Math' as global variable
|
||||
if (!_globals->propExists("Math")) {
|
||||
ScValue val(_game);
|
||||
val.setNative(_game->_mathClass, true);
|
||||
_globals->setProp("Math", &val);
|
||||
}
|
||||
|
||||
// register 'Directory' as global variable
|
||||
if (!_globals->propExists("Directory")) {
|
||||
ScValue val(_game);
|
||||
val.setNative(_game->_directoryClass, true);
|
||||
_globals->setProp("Directory", &val);
|
||||
}
|
||||
|
||||
// prepare script cache
|
||||
for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
|
||||
_cachedScripts[i] = nullptr;
|
||||
}
|
||||
|
||||
_currentScript = nullptr;
|
||||
|
||||
_isProfiling = false;
|
||||
_profilingStartTime = 0;
|
||||
|
||||
//enableProfiling();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScEngine::~ScEngine() {
|
||||
_game->LOG(0, "Shutting down scripting engine");
|
||||
|
||||
disableProfiling();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::cleanup() {
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (!_scripts[i]->_thread && _scripts[i]->_owner) {
|
||||
_scripts[i]->_owner->removeScript(_scripts[i]);
|
||||
}
|
||||
delete _scripts[i];
|
||||
_scripts.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
|
||||
_scripts.removeAll();
|
||||
|
||||
SAFE_DELETE(_globals);
|
||||
|
||||
emptyScriptCache();
|
||||
|
||||
_currentScript = nullptr; // ref only
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
byte *ScEngine::loadFile(void *data, char *filename, uint32 *size) {
|
||||
BaseGame *game = (BaseGame *)data;
|
||||
return game->_fileManager->readWholeFile(filename, size);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScEngine::closeFile(void *data, byte *buffer) {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScEngine::parseElement(void *data, int line, int type, void *elementData) {
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScScript *ScEngine::runScript(const char *filename, BaseScriptHolder *owner) {
|
||||
byte *compBuffer;
|
||||
uint32 compSize;
|
||||
|
||||
// get script from cache
|
||||
compBuffer = getCompiledScript(filename, &compSize);
|
||||
if (!compBuffer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// add new script
|
||||
#if EXTENDED_DEBUGGER_ENABLED
|
||||
DebuggableScEngine* debuggableEngine;
|
||||
debuggableEngine = dynamic_cast<DebuggableScEngine*>(this);
|
||||
// TODO: Not pretty
|
||||
assert(debuggableEngine);
|
||||
ScScript *script = new DebuggableScript(_game, debuggableEngine);
|
||||
#else
|
||||
ScScript *script = new ScScript(_game, this);
|
||||
#endif
|
||||
bool ret = script->create(filename, compBuffer, compSize, owner);
|
||||
if (DID_FAIL(ret)) {
|
||||
_game->LOG(ret, "Error running script '%s'...", filename);
|
||||
delete script;
|
||||
return nullptr;
|
||||
} else {
|
||||
// publish the "self" pseudo-variable
|
||||
ScValue val(_game);
|
||||
if (owner) {
|
||||
val.setNative(owner, true);
|
||||
} else {
|
||||
val.setNULL();
|
||||
}
|
||||
|
||||
script->_globals->setProp("self", &val);
|
||||
script->_globals->setProp("this", &val);
|
||||
|
||||
_scripts.add(script);
|
||||
|
||||
return script;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::isRunningScript(const char *filename) {
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (strcmp(_scripts[i]->_filename, filename) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache) {
|
||||
// is script in cache?
|
||||
if (!ignoreCache) {
|
||||
for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
|
||||
if (_cachedScripts[i] && scumm_stricmp(_cachedScripts[i]->_filename, filename) == 0) {
|
||||
_cachedScripts[i]->_timestamp = BasePlatform::getTime();
|
||||
*outSize = _cachedScripts[i]->_size;
|
||||
return _cachedScripts[i]->_buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nope, load it
|
||||
byte *compBuffer;
|
||||
uint32 compSize;
|
||||
|
||||
uint32 size;
|
||||
|
||||
byte *buffer = _game->_fileManager->readWholeFile(filename, &size);
|
||||
if (!buffer) {
|
||||
_game->LOG(0, "ScEngine::getCompiledScript - error opening script '%s'", filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// needs to be compiled?
|
||||
if (READ_LE_UINT32(buffer) == SCRIPT_MAGIC) {
|
||||
compBuffer = buffer;
|
||||
compSize = size;
|
||||
} else {
|
||||
if (!_compilerAvailable) {
|
||||
_game->LOG(0, "ScEngine::getCompiledScript - script '%s' needs to be compiled but compiler is not available", filename);
|
||||
delete[] buffer;
|
||||
return nullptr;
|
||||
}
|
||||
// This code will never be called, since _compilerAvailable is const false.
|
||||
// It's only here in the event someone would want to reinclude the compiler.
|
||||
error("Script needs compilation, ScummVM does not contain a WME compiler");
|
||||
}
|
||||
|
||||
byte *ret = nullptr;
|
||||
|
||||
// add script to cache
|
||||
CScCachedScript *cachedScript = new CScCachedScript(filename, compBuffer, compSize);
|
||||
if (cachedScript) {
|
||||
int index = 0;
|
||||
uint32 minTime = BasePlatform::getTime();
|
||||
for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
|
||||
if (_cachedScripts[i] == nullptr) {
|
||||
index = i;
|
||||
break;
|
||||
} else if (_cachedScripts[i]->_timestamp <= minTime) {
|
||||
minTime = _cachedScripts[i]->_timestamp;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (_cachedScripts[index] != nullptr) {
|
||||
delete _cachedScripts[index];
|
||||
}
|
||||
_cachedScripts[index] = cachedScript;
|
||||
|
||||
ret = cachedScript->_buffer;
|
||||
*outSize = cachedScript->_size;
|
||||
}
|
||||
|
||||
|
||||
// cleanup
|
||||
delete[] buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::tick() {
|
||||
if (_scripts.getSize() == 0) {
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
// resolve waiting scripts
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
|
||||
switch (_scripts[i]->_state) {
|
||||
case SCRIPT_WAITING: {
|
||||
/*
|
||||
bool obj_found=false;
|
||||
for(int j=0; j<_game->_regObjects.size(); j++)
|
||||
{
|
||||
if (_game->_regObjects[j] == _scripts[i]->_waitObject)
|
||||
{
|
||||
if (_game->_regObjects[j]->IsReady()) _scripts[i]->Run();
|
||||
obj_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!obj_found) _scripts[i]->finish(); // _waitObject no longer exists
|
||||
*/
|
||||
if (_game->validObject(_scripts[i]->_waitObject)) {
|
||||
if (_scripts[i]->_waitObject->isReady()) {
|
||||
_scripts[i]->run();
|
||||
}
|
||||
} else {
|
||||
_scripts[i]->finish();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_SLEEPING: {
|
||||
if (_scripts[i]->_waitFrozen) {
|
||||
if (_scripts[i]->_waitTime <= BasePlatform::getTime()) {
|
||||
_scripts[i]->run();
|
||||
}
|
||||
} else {
|
||||
if (_scripts[i]->_waitTime <= _game->_timer) {
|
||||
_scripts[i]->run();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_WAITING_SCRIPT: {
|
||||
if (!isValidScript(_scripts[i]->_waitScript) || _scripts[i]->_waitScript->_state == SCRIPT_ERROR) {
|
||||
// fake return value
|
||||
_scripts[i]->_stack->pushNULL();
|
||||
_scripts[i]->_waitScript = nullptr;
|
||||
_scripts[i]->run();
|
||||
} else {
|
||||
if (_scripts[i]->_waitScript->_state == SCRIPT_THREAD_FINISHED) {
|
||||
// copy return value
|
||||
_scripts[i]->_stack->push(_scripts[i]->_waitScript->_stack->pop());
|
||||
_scripts[i]->run();
|
||||
_scripts[i]->_waitScript->finish();
|
||||
_scripts[i]->_waitScript = nullptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
} // for each script
|
||||
|
||||
|
||||
// execute scripts
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
|
||||
// skip paused scripts
|
||||
if (_scripts[i]->_state == SCRIPT_PAUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// time sliced script
|
||||
if (_scripts[i]->_timeSlice > 0) {
|
||||
uint32 startTime = BasePlatform::getTime();
|
||||
while (_scripts[i]->_state == SCRIPT_RUNNING && BasePlatform::getTime() - startTime < _scripts[i]->_timeSlice) {
|
||||
_currentScript = _scripts[i];
|
||||
_scripts[i]->executeInstruction();
|
||||
}
|
||||
if (_isProfiling && _scripts[i]->_filename && _scripts[i]->_filename[0]) {
|
||||
addScriptTime(_scripts[i]->_filename, BasePlatform::getTime() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
// normal script
|
||||
else {
|
||||
uint32 startTime = 0;
|
||||
bool isProfiling = _isProfiling;
|
||||
if (isProfiling) {
|
||||
startTime = BasePlatform::getTime();
|
||||
}
|
||||
|
||||
while (_scripts[i]->_state == SCRIPT_RUNNING) {
|
||||
_currentScript = _scripts[i];
|
||||
_scripts[i]->executeInstruction();
|
||||
}
|
||||
if (isProfiling && _scripts[i]->_filename && _scripts[i]->_filename[0]) {
|
||||
addScriptTime(_scripts[i]->_filename, BasePlatform::getTime() - startTime);
|
||||
}
|
||||
}
|
||||
_currentScript = nullptr;
|
||||
}
|
||||
|
||||
removeFinishedScripts();
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::tickUnbreakable() {
|
||||
ScScript *oldScript = _currentScript;
|
||||
|
||||
// execute unbreakable scripts
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (!_scripts[i]->_unbreakable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (_scripts[i]->_state == SCRIPT_RUNNING) {
|
||||
_currentScript = _scripts[i];
|
||||
_scripts[i]->executeInstruction();
|
||||
}
|
||||
_scripts[i]->finish();
|
||||
_currentScript = oldScript;
|
||||
}
|
||||
|
||||
// NB: Don't remove finished scripts here since we could be recursively
|
||||
// executing scripts. Doing so could invalidate the outer iteration in
|
||||
// ::tick() over _scripts.
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::removeFinishedScripts() {
|
||||
// remove finished scripts
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR) {
|
||||
if (!_scripts[i]->_thread && _scripts[i]->_owner) {
|
||||
_scripts[i]->_owner->removeScript(_scripts[i]);
|
||||
}
|
||||
|
||||
delete _scripts[i];
|
||||
_scripts.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int ScEngine::getNumScripts(int *running, int *waiting, int *persistent) {
|
||||
int numRunning = 0, numWaiting = 0, numPersistent = 0, numTotal = 0;
|
||||
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (_scripts[i]->_state == SCRIPT_FINISHED) {
|
||||
continue;
|
||||
}
|
||||
switch (_scripts[i]->_state) {
|
||||
case SCRIPT_RUNNING:
|
||||
case SCRIPT_SLEEPING:
|
||||
case SCRIPT_PAUSED:
|
||||
numRunning++;
|
||||
break;
|
||||
case SCRIPT_WAITING:
|
||||
numWaiting++;
|
||||
break;
|
||||
case SCRIPT_PERSISTENT:
|
||||
numPersistent++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
numTotal++;
|
||||
}
|
||||
if (running) {
|
||||
*running = numRunning;
|
||||
}
|
||||
if (waiting) {
|
||||
*waiting = numWaiting;
|
||||
}
|
||||
if (persistent) {
|
||||
*persistent = numPersistent;
|
||||
}
|
||||
|
||||
return numTotal;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::emptyScriptCache() {
|
||||
for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
|
||||
if (_cachedScripts[i]) {
|
||||
SAFE_DELETE(_cachedScripts[i]);
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::resetObject(BaseObject *object) {
|
||||
// terminate all scripts waiting for this object
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (_scripts[i]->_state == SCRIPT_WAITING && _scripts[i]->_waitObject == object) {
|
||||
if (!_game->_compatKillMethodThreads) {
|
||||
resetScript(_scripts[i]);
|
||||
}
|
||||
|
||||
bool isThread = _scripts[i]->_methodThread || _scripts[i]->_thread;
|
||||
_scripts[i]->finish(!isThread); // 1.9b1 - top-level script kills its threads as well
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::resetScript(ScScript *script) {
|
||||
// terminate all scripts waiting for this script
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (_scripts[i]->_state == SCRIPT_WAITING_SCRIPT && _scripts[i]->_waitScript == script) {
|
||||
_scripts[i]->finish();
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::persist(BasePersistenceManager *persistMgr) {
|
||||
if (!persistMgr->getIsSaving()) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_game));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_currentScript));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_globals));
|
||||
_scripts.persist(persistMgr);
|
||||
|
||||
// initialise to defaults
|
||||
if (!persistMgr->getIsSaving()) {
|
||||
_isProfiling = false;
|
||||
_profilingStartTime = 0;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScEngine::editorCleanup() {
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (_scripts[i]->_owner == nullptr && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) {
|
||||
delete _scripts[i];
|
||||
_scripts.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::pauseAll() {
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (_scripts[i] != _currentScript) {
|
||||
_scripts[i]->pause();
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::resumeAll() {
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
_scripts[i]->resume();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::isValidScript(ScScript *script) {
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
if (_scripts[i] == script) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScEngine::clearGlobals(bool includingNatives) {
|
||||
_globals->cleanProps(includingNatives);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScEngine::addScriptTime(const char *filename, uint32 time) {
|
||||
if (!_isProfiling) {
|
||||
return;
|
||||
}
|
||||
|
||||
AnsiString fileName = filename;
|
||||
fileName.toLowercase();
|
||||
_scriptTimes[fileName] += time;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScEngine::enableProfiling() {
|
||||
if (_isProfiling) {
|
||||
return;
|
||||
}
|
||||
|
||||
// destroy old data, if any
|
||||
_scriptTimes.clear();
|
||||
|
||||
_profilingStartTime = BasePlatform::getTime();
|
||||
_isProfiling = true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScEngine::disableProfiling() {
|
||||
if (!_isProfiling) {
|
||||
return;
|
||||
}
|
||||
|
||||
dumpStats();
|
||||
_isProfiling = false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScEngine::dumpStats() {
|
||||
error("DumpStats not ported to ScummVM yet");
|
||||
/* uint32 totalTime = BasePlatform::getTime() - _profilingStartTime;
|
||||
|
||||
typedef std::vector <std::pair<uint32, std::string> > TimeVector;
|
||||
TimeVector times;
|
||||
|
||||
ScriptTimes::iterator it;
|
||||
for (it = _scriptTimes.begin(); it != _scriptTimes.end(); ++it) {
|
||||
times.push_back(std::pair<uint32, std::string> (it->_value, it->_key));
|
||||
}
|
||||
std::sort(times.begin(), times.end());
|
||||
|
||||
|
||||
TimeVector::reverse_iterator tit;
|
||||
|
||||
_game->LOG(0, "***** Script profiling information: *****");
|
||||
_game->LOG(0, " %-40s %fs", "Total execution time", (float)totalTime / 1000);
|
||||
|
||||
for (tit = times.rbegin(); tit != times.rend(); ++tit) {
|
||||
_game->LOG(0, " %-40s %fs (%f%%)", tit->second.c_str(), (float)tit->first / 1000, (float)tit->first / (float)totalTime * 100);
|
||||
}*/
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
126
engines/wintermute/base/scriptables/script_engine.h
Normal file
126
engines/wintermute/base/scriptables/script_engine.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SCENGINE_H
|
||||
#define WINTERMUTE_SCENGINE_H
|
||||
|
||||
#include "engines/wintermute/persistent.h"
|
||||
#include "engines/wintermute/coll_templ.h"
|
||||
#include "engines/wintermute/base/base.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
#define MAX_CACHED_SCRIPTS 20
|
||||
class ScScript;
|
||||
class ScValue;
|
||||
class BaseObject;
|
||||
class BaseScriptHolder;
|
||||
class ScEngine : public BaseClass {
|
||||
public:
|
||||
class CScCachedScript {
|
||||
public:
|
||||
CScCachedScript(const char *filename, byte *buffer, uint32 size) {
|
||||
_timestamp = BasePlatform::getTime();
|
||||
_buffer = new byte[size];
|
||||
if (_buffer) {
|
||||
memcpy(_buffer, buffer, size);
|
||||
}
|
||||
_size = size;
|
||||
size_t filenameSize = strlen(filename) + 1;
|
||||
_filename = new char[filenameSize];
|
||||
Common::strcpy_s(_filename, filenameSize, filename);
|
||||
};
|
||||
|
||||
~CScCachedScript() {
|
||||
if (_buffer) {
|
||||
delete[] _buffer;
|
||||
}
|
||||
if (_filename)
|
||||
delete[] _filename;
|
||||
};
|
||||
|
||||
uint32 _timestamp;
|
||||
byte *_buffer;
|
||||
uint32 _size;
|
||||
char *_filename;
|
||||
};
|
||||
|
||||
public:
|
||||
bool clearGlobals(bool includingNatives = false);
|
||||
bool tickUnbreakable();
|
||||
bool removeFinishedScripts();
|
||||
bool isValidScript(ScScript *script);
|
||||
|
||||
ScScript *_currentScript;
|
||||
bool resumeAll();
|
||||
bool pauseAll();
|
||||
void editorCleanup();
|
||||
bool resetObject(BaseObject *object);
|
||||
bool resetScript(ScScript *script);
|
||||
bool emptyScriptCache();
|
||||
byte *getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache = false);
|
||||
DECLARE_PERSISTENT(ScEngine, BaseClass)
|
||||
bool cleanup();
|
||||
int getNumScripts(int *running = nullptr, int *waiting = nullptr, int *persistent = nullptr);
|
||||
bool tick();
|
||||
ScValue *_globals;
|
||||
ScScript *runScript(const char *filename, BaseScriptHolder *owner = nullptr);
|
||||
bool isRunningScript(const char *filename);
|
||||
static const bool _compilerAvailable = false;
|
||||
|
||||
ScEngine(BaseGame *inGame);
|
||||
~ScEngine() override;
|
||||
static byte *loadFile(void *data, char *filename, uint32 *size);
|
||||
static void closeFile(void *data, byte *buffer);
|
||||
static void parseElement(void *data, int line, int type, void *elementData);
|
||||
|
||||
BaseArray<ScScript *> _scripts;
|
||||
|
||||
void enableProfiling();
|
||||
void disableProfiling();
|
||||
bool isProfiling() {
|
||||
return _isProfiling;
|
||||
}
|
||||
|
||||
void addScriptTime(const char *filename, uint32 time);
|
||||
void dumpStats();
|
||||
|
||||
private:
|
||||
|
||||
CScCachedScript *_cachedScripts[MAX_CACHED_SCRIPTS];
|
||||
bool _isProfiling;
|
||||
uint32 _profilingStartTime;
|
||||
|
||||
typedef Common::HashMap<Common::String, uint32> ScriptTimes;
|
||||
ScriptTimes _scriptTimes;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
278
engines/wintermute/base/scriptables/script_ext_array.cpp
Normal file
278
engines/wintermute/base/scriptables/script_ext_array.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/persistent.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/system/sys_instance.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_array.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXArray, false)
|
||||
|
||||
BaseScriptable *makeSXArray(BaseGame *inGame, ScStack *stack) {
|
||||
return new SXArray(inGame, stack);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXArray::SXArray(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
|
||||
_length = 0;
|
||||
_values = new ScValue(_game);
|
||||
|
||||
int numParams = stack->pop()->getInt(0);
|
||||
|
||||
if (numParams == 1) {
|
||||
_length = stack->pop()->getInt(0);
|
||||
} else if (numParams > 1) {
|
||||
_length = numParams;
|
||||
char paramName[20];
|
||||
for (int i = 0; i < numParams; i++) {
|
||||
Common::sprintf_s(paramName, "%d", i);
|
||||
_values->setProp(paramName, stack->pop());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXArray::SXArray(BaseGame *inGame) : BaseScriptable(inGame) {
|
||||
_length = 0;
|
||||
_values = new ScValue(_game);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXArray::~SXArray() {
|
||||
SAFE_DELETE(_values);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *SXArray::scToString() {
|
||||
static char dummy[32768];
|
||||
dummy[0] = '\0';
|
||||
char propName[20];
|
||||
for (int i = 0; i < _length; i++) {
|
||||
Common::sprintf_s(propName, "%d", i);
|
||||
ScValue *val = _values->getProp(propName);
|
||||
if (val) {
|
||||
if (strlen(dummy) + strlen(val->getString()) < 32768) {
|
||||
Common::strcat_s(dummy, val->getString());
|
||||
}
|
||||
}
|
||||
|
||||
if (i < _length - 1 && strlen(dummy) + 1 < 32768) {
|
||||
Common::strcat_s(dummy, ",");
|
||||
}
|
||||
}
|
||||
return dummy;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Push
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Push") == 0) {
|
||||
int numParams = stack->pop()->getInt(0);
|
||||
char paramName[20];
|
||||
|
||||
for (int i = 0; i < numParams; i++) {
|
||||
_length++;
|
||||
Common::sprintf_s(paramName, "%d", _length - 1);
|
||||
_values->setProp(paramName, stack->pop(), true);
|
||||
}
|
||||
stack->pushInt(_length);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Pop
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Pop") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
if (_length > 0) {
|
||||
char paramName[20];
|
||||
Common::sprintf_s(paramName, "%d", _length - 1);
|
||||
stack->push(_values->getProp(paramName));
|
||||
_values->deleteProp(paramName);
|
||||
_length--;
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// [FoxTail] Delete
|
||||
// Removes item from array by index, shifting other elements
|
||||
// Used to shuffle arrays and delete found items in various scripts
|
||||
// Return value is never used
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Delete") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
int shiftPoint = stack->pop()->getInt(0);
|
||||
char paramNameFrom[20];
|
||||
char paramNameTo[20];
|
||||
|
||||
for (int i = shiftPoint; i < _length - 1 ; i++) {
|
||||
Common::sprintf_s(paramNameFrom, "%d", i + 1);
|
||||
Common::sprintf_s(paramNameTo, "%d", i);
|
||||
_values->setProp(paramNameTo, _values->getProp(paramNameFrom), false);
|
||||
}
|
||||
_values->deleteProp(paramNameFrom);
|
||||
_length--;
|
||||
stack->pushNULL();
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXArray::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("array");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Length
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Length") == 0) {
|
||||
_scValue->setInt(_length);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// [number]
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else {
|
||||
char paramName[20];
|
||||
if (validNumber(name, paramName)) {
|
||||
return _values->getProp(paramName);
|
||||
} else {
|
||||
return _scValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXArray::scSetProperty(const char *name, ScValue *value) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Length
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Length") == 0) {
|
||||
int origLength = _length;
|
||||
_length = MAX(value->getInt(0), 0);
|
||||
|
||||
char propName[20];
|
||||
if (_length < origLength) {
|
||||
for (int i = _length; i < origLength; i++) {
|
||||
Common::sprintf_s(propName, "%d", i);
|
||||
_values->deleteProp(propName);
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// [number]
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else {
|
||||
char paramName[20];
|
||||
if (validNumber(name, paramName)) {
|
||||
int index = atoi(paramName);
|
||||
if (index >= _length) {
|
||||
_length = index + 1;
|
||||
}
|
||||
return _values->setProp(paramName, value);
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXArray::persist(BasePersistenceManager *persistMgr) {
|
||||
BaseScriptable::persist(persistMgr);
|
||||
|
||||
persistMgr->transferSint32(TMEMBER(_length));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_values));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXArray::validNumber(const char *origStr, char *outStr) {
|
||||
bool isNumber = true;
|
||||
for (uint32 i = 0; i < strlen(origStr); i++) {
|
||||
if (!(origStr[i] >= '0' && origStr[i] <= '9')) {
|
||||
isNumber = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumber) {
|
||||
int index = atoi(origStr);
|
||||
Common::sprintf_s(outStr, 20, "%d", index);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXArray::push(ScValue *val) {
|
||||
char paramName[20];
|
||||
_length++;
|
||||
Common::sprintf_s(paramName, "%d", _length - 1);
|
||||
_values->setProp(paramName, val, true);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
53
engines/wintermute/base/scriptables/script_ext_array.h
Normal file
53
engines/wintermute/base/scriptables/script_ext_array.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SXARRAY_H
|
||||
#define WINTERMUTE_SXARRAY_H
|
||||
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXArray : public BaseScriptable {
|
||||
public:
|
||||
bool push(ScValue *val);
|
||||
bool validNumber(const char *origStr, char *outStr);
|
||||
DECLARE_PERSISTENT(SXArray, BaseScriptable)
|
||||
SXArray(BaseGame *inGame, ScStack *stack);
|
||||
SXArray(BaseGame *inGame);
|
||||
~SXArray() override;
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
int32 _length;
|
||||
ScValue *_values;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
320
engines/wintermute/base/scriptables/script_ext_date.cpp
Normal file
320
engines/wintermute/base/scriptables/script_ext_date.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_date.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXDate, false)
|
||||
|
||||
BaseScriptable *makeSXDate(BaseGame *inGame, ScStack *stack) {
|
||||
return new SXDate(inGame, stack);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXDate::SXDate(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
|
||||
stack->correctParams(6);
|
||||
|
||||
memset(&_tm, 0, sizeof(_tm));
|
||||
|
||||
ScValue *valYear = stack->pop();
|
||||
_tm.tm_year = valYear->getInt() - 1900;
|
||||
_tm.tm_mon = stack->pop()->getInt() - 1;
|
||||
_tm.tm_mday = stack->pop()->getInt();
|
||||
_tm.tm_hour = stack->pop()->getInt();
|
||||
_tm.tm_min = stack->pop()->getInt();
|
||||
_tm.tm_sec = stack->pop()->getInt();
|
||||
|
||||
if (valYear->isNULL()) {
|
||||
g_system->getTimeAndDate(_tm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXDate::~SXDate() {
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *SXDate::scToString() {
|
||||
// TODO: Make this more stringy, and less ISO 8601-like
|
||||
_strRep.format("%04d-%02d-%02d - %02d:%02d:%02d", _tm.tm_year, _tm.tm_mon, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec);
|
||||
return _strRep.c_str();
|
||||
//return asctime(&_tm);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXDate::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetYear
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "GetYear") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_year + 1900);
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetMonth
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetMonth") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_mon + 1);
|
||||
return STATUS_OK;
|
||||
}
|
||||
#ifdef ENABLE_FOXTAIL
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// [FoxTail] GetDay
|
||||
// date.GetDate() was renamed to date.GetDay() in FoxTail 1.2.896 engine
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetDay") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_mday);
|
||||
return STATUS_OK;
|
||||
}
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetDate
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetDate") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_mday);
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetHours
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetHours") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_hour);
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetMinutes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetMinutes") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_min);
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetSeconds
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetSeconds") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_sec);
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetWeekday
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetWeekday") == 0) {
|
||||
stack->correctParams(0);
|
||||
stack->pushInt(_tm.tm_wday);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetYear
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetYear") == 0) {
|
||||
stack->correctParams(1);
|
||||
_tm.tm_year = stack->pop()->getInt() - 1900;
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetMonth
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetMonth") == 0) {
|
||||
stack->correctParams(1);
|
||||
_tm.tm_mon = stack->pop()->getInt() - 1;
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetDate
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetDate") == 0) {
|
||||
stack->correctParams(1);
|
||||
_tm.tm_mday = stack->pop()->getInt();
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetHours
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetHours") == 0) {
|
||||
stack->correctParams(1);
|
||||
_tm.tm_hour = stack->pop()->getInt();
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetMinutes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetMinutes") == 0) {
|
||||
stack->correctParams(1);
|
||||
_tm.tm_min = stack->pop()->getInt();
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetSeconds
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetSeconds") == 0) {
|
||||
stack->correctParams(1);
|
||||
_tm.tm_sec = stack->pop()->getInt();
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetCurrentTime
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetCurrentTime") == 0) {
|
||||
stack->correctParams(0);
|
||||
g_system->getTimeAndDate(_tm);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXDate::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("date");
|
||||
return _scValue;
|
||||
} else {
|
||||
return _scValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXDate::scSetProperty(const char *name, ScValue *value) {
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Name") == 0) {
|
||||
setName(value->getString());
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
else*/ return STATUS_FAILED;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXDate::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseScriptable::persist(persistMgr);
|
||||
int32 year = _tm.tm_year;
|
||||
int32 mon = _tm.tm_mon;
|
||||
int32 mday = _tm.tm_mday;
|
||||
int32 hour = _tm.tm_hour;
|
||||
int32 min = _tm.tm_min;
|
||||
int32 sec = _tm.tm_sec;
|
||||
persistMgr->transferSint32(TMEMBER(year));
|
||||
persistMgr->transferSint32(TMEMBER(mon));
|
||||
persistMgr->transferSint32(TMEMBER(mday));
|
||||
persistMgr->transferSint32(TMEMBER(hour));
|
||||
persistMgr->transferSint32(TMEMBER(min));
|
||||
persistMgr->transferSint32(TMEMBER(sec));
|
||||
if (persistMgr->checkVersion(1, 2, 1)) {
|
||||
int32 wday = _tm.tm_wday;
|
||||
persistMgr->transferSint32(TMEMBER(wday));
|
||||
_tm.tm_wday = wday;
|
||||
}
|
||||
_tm.tm_year = year;
|
||||
_tm.tm_mon = mon;
|
||||
_tm.tm_mday = mday;
|
||||
_tm.tm_hour = hour;
|
||||
_tm.tm_min = min;
|
||||
_tm.tm_sec = sec;
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int SXDate::scCompare(BaseScriptable *value) {
|
||||
TimeDate time1 = _tm;
|
||||
TimeDate time2 = ((SXDate *)value)->_tm;
|
||||
|
||||
if (time1.tm_year < time2.tm_year) {
|
||||
return -1;
|
||||
} else if (time1.tm_year == time2.tm_year) {
|
||||
if (time1.tm_mon < time2.tm_mon) {
|
||||
return -1;
|
||||
} else if (time1.tm_mon == time2.tm_mon) {
|
||||
if (time1.tm_mday < time2.tm_mday) {
|
||||
return -1;
|
||||
} else if (time1.tm_mday == time2.tm_mday) {
|
||||
if (time1.tm_hour < time2.tm_hour) {
|
||||
return -1;
|
||||
} else if (time1.tm_hour == time2.tm_hour) {
|
||||
if (time1.tm_min < time2.tm_min) {
|
||||
return -1;
|
||||
} else if (time1.tm_min == time2.tm_min) {
|
||||
if (time1.tm_sec < time2.tm_sec) {
|
||||
return -1;
|
||||
} else if (time1.tm_sec == time2.tm_sec) {
|
||||
return 0; // Equal
|
||||
} else {
|
||||
return 1; // Sec
|
||||
}
|
||||
} else {
|
||||
return 1; // Minute
|
||||
}
|
||||
} else {
|
||||
return 1; // Hour
|
||||
}
|
||||
} else {
|
||||
return 1; // Day
|
||||
}
|
||||
} else {
|
||||
return 1; // Month
|
||||
}
|
||||
} else {
|
||||
return 1; // Year
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
53
engines/wintermute/base/scriptables/script_ext_date.h
Normal file
53
engines/wintermute/base/scriptables/script_ext_date.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SXDATE_H
|
||||
#define WINTERMUTE_SXDATE_H
|
||||
|
||||
#include "common/system.h"
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXDate : public BaseScriptable {
|
||||
public:
|
||||
int scCompare(BaseScriptable *value) override;
|
||||
DECLARE_PERSISTENT(SXDate, BaseScriptable)
|
||||
SXDate(BaseGame *inGame, ScStack *stack);
|
||||
~SXDate() override;
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
TimeDate _tm;
|
||||
|
||||
Common::String _strRep;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
207
engines/wintermute/base/scriptables/script_ext_directory.cpp
Normal file
207
engines/wintermute/base/scriptables/script_ext_directory.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_array.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_directory.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/persistent.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXDirectory, true)
|
||||
|
||||
BaseScriptable *makeSXDirectory(BaseGame *inGame) {
|
||||
return new SXDirectory(inGame);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXDirectory::SXDirectory(BaseGame *inGame) : BaseScriptable(inGame) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXDirectory::~SXDirectory() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXDirectory::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Create
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Create") == 0) {
|
||||
stack->correctParams(1);
|
||||
const char *dirName = stack->pop()->getString();
|
||||
|
||||
if (strcmp(dirName, "saves") == 0) {
|
||||
// Known games that do this: alphapolaris, hamlet, lostbride, papasdaughters1, papasdaughters2, polechudes, etc
|
||||
// No need to actually create anything, files will be stored at SavefileManager
|
||||
stack->pushBool(true);
|
||||
} else {
|
||||
// No currently known games need this
|
||||
warning("Directory.Create is not implemented! Returning false...");
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Delete
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Delete") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pop()->getString();
|
||||
|
||||
// No currently known games need this
|
||||
warning("Directory.Delete is not implemented! Returning false...");
|
||||
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetFiles / GetDirectories
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetFiles") == 0 || strcmp(name, "GetDirectories") == 0) {
|
||||
stack->correctParams(2);
|
||||
const char *dirName = stack->pop()->getString();
|
||||
stack->pop()->getString();
|
||||
|
||||
stack->pushInt(0);
|
||||
BaseScriptable *array = makeSXArray(_game, stack);
|
||||
|
||||
if (strcmp(dirName, "saves") == 0 && strcmp(name, "GetFiles") == 0) {
|
||||
// used in "Tale of The Lost Bride and A Hidden Treasure"
|
||||
// returns list of saves, removing "lostbride-win-ru.saves_" prefix
|
||||
|
||||
Common::StringArray fnames;
|
||||
BaseFileManager::getEngineInstance()->listMatchingFiles(fnames, "*");
|
||||
for (uint32 i = 0; i < fnames.size(); i++) {
|
||||
stack->pushString(fnames[i].c_str());
|
||||
((SXArray *)array)->push(stack->pop());
|
||||
}
|
||||
|
||||
} else if (strcmp(dirName, "X:\\FBI\\data\\scenes\\17-magic\\") == 0 && strcmp(name, "GetDirectories") == 0) {
|
||||
// used in secret scene of "Art of Murder 1: FBI Confidential"
|
||||
// TODO: return list of "scenes\17-magic" subfolders from data.dcp
|
||||
|
||||
warning("FBI\\scenes\\17-magic Directory.%s is not implemented! Returning empty array...", name);
|
||||
|
||||
} else if (strcmp(dirName, ".\\") == 0 && strcmp(name, "GetFiles") == 0) {
|
||||
// Used in "Stroke of Fate: Operation Valkyrie" and "Stroke of Fate: Operation Bunker"
|
||||
// to return list of log files to be removed.
|
||||
|
||||
// return empty list instead
|
||||
|
||||
} else {
|
||||
// No currently known games need this
|
||||
|
||||
warning("Directory.%s is not implemented! Returning empty array...", name);
|
||||
|
||||
}
|
||||
|
||||
stack->pushNative(array, false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetDrives
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetDrives") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
// No currently known games do this
|
||||
warning("Directory.GetDrives is not implemented! Returning empty array...");
|
||||
|
||||
stack->pushInt(0);
|
||||
stack->pushNative(makeSXArray(_game, stack), false);
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXDirectory::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("directory");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PathSeparator
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "PathSeparator") == 0) {
|
||||
_scValue->setString("\\");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CurrentDirectory
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "CurrentDirectory") == 0) {
|
||||
_scValue->setString("."); // See also: BaseGame::scGetProperty("SaveDirectory")
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TempDirectory
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "TempDirectory") == 0) {
|
||||
_scValue->setString("temp"); // See also: BaseGame::scGetProperty("SaveDirectory")
|
||||
return _scValue;
|
||||
} else {
|
||||
return _scValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXDirectory::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseScriptable::persist(persistMgr);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
47
engines/wintermute/base/scriptables/script_ext_directory.h
Normal file
47
engines/wintermute/base/scriptables/script_ext_directory.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SXDIRECTORY_H
|
||||
#define WINTERMUTE_SXDIRECTORY_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXDirectory : public BaseScriptable {
|
||||
public:
|
||||
DECLARE_PERSISTENT(SXDirectory, BaseScriptable)
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
SXDirectory(BaseGame *inGame);
|
||||
~SXDirectory() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
826
engines/wintermute/base/scriptables/script_ext_file.cpp
Normal file
826
engines/wintermute/base/scriptables/script_ext_file.cpp
Normal file
@@ -0,0 +1,826 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/system/sys_class_registry.h"
|
||||
#include "engines/wintermute/system/sys_class.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script.h"
|
||||
#include "engines/wintermute/utils/utils.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/base/file/base_savefile_manager_file.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_file.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
// Note: This code is completely untested, as I have yet to find a game that uses SXFile.
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXFile, false)
|
||||
|
||||
BaseScriptable *makeSXFile(BaseGame *inGame, ScStack *stack) {
|
||||
return new SXFile(inGame, stack);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXFile::SXFile(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
|
||||
stack->correctParams(1);
|
||||
ScValue *val = stack->pop();
|
||||
|
||||
_filename = nullptr;
|
||||
if (!val->isNULL()) {
|
||||
BaseUtils::setString(&_filename, val->getString());
|
||||
}
|
||||
|
||||
_readFile = nullptr;
|
||||
_writeFile = nullptr;
|
||||
|
||||
_mode = 0;
|
||||
_textMode = false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXFile::~SXFile() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SXFile::cleanup() {
|
||||
SAFE_DELETE_ARRAY(_filename);
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SXFile::close() {
|
||||
if (_readFile) {
|
||||
_game->_fileManager->closeFile(_readFile);
|
||||
_readFile = nullptr;
|
||||
}
|
||||
if (_writeFile) {
|
||||
_writeFile->finalize();
|
||||
SAFE_DELETE(_writeFile);
|
||||
}
|
||||
_mode = 0;
|
||||
_textMode = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *SXFile::scToString() {
|
||||
if (_filename && _filename[0]) {
|
||||
return _filename;
|
||||
} else {
|
||||
return "[file object]";
|
||||
}
|
||||
}
|
||||
|
||||
#define FILE_BUFFER_SIZE 32768
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXFile::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetFilename
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "SetFilename") == 0) {
|
||||
stack->correctParams(1);
|
||||
const char *filename = stack->pop()->getString();
|
||||
cleanup();
|
||||
BaseUtils::setString(&_filename, filename);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// OpenAsText / OpenAsBinary
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "OpenAsText") == 0 || strcmp(name, "OpenAsBinary") == 0) {
|
||||
stack->correctParams(1);
|
||||
close();
|
||||
_mode = stack->pop()->getInt(1);
|
||||
if (_mode < 1 || _mode > 3) {
|
||||
script->runtimeError("File.%s: invalid access mode. Setting read mode.", name);
|
||||
_mode = 1;
|
||||
}
|
||||
if (_mode == 1) {
|
||||
_readFile = _game->_fileManager->openFile(_filename);
|
||||
if (!_readFile) {
|
||||
//script->runtimeError("File.%s: Error opening file '%s' for reading.", name, _filename);
|
||||
close();
|
||||
} else {
|
||||
_textMode = strcmp(name, "OpenAsText") == 0;
|
||||
}
|
||||
} else {
|
||||
if (strcmp(name, "OpenAsText") == 0) {
|
||||
if (_mode == 2) {
|
||||
_writeFile = openForWrite(_filename, false);
|
||||
} else {
|
||||
_writeFile = openForAppend(_filename, false);
|
||||
}
|
||||
} else {
|
||||
if (_mode == 2) {
|
||||
_writeFile = openForWrite(_filename, true);
|
||||
} else {
|
||||
_writeFile = openForAppend(_filename, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_writeFile) {
|
||||
//script->runtimeError("File.%s: Error opening file '%s' for writing.", name, _filename);
|
||||
close();
|
||||
} else {
|
||||
_textMode = strcmp(name, "OpenAsText") == 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (_readFile || _writeFile) {
|
||||
stack->pushBool(true);
|
||||
} else {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Close
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Close") == 0) {
|
||||
stack->correctParams(0);
|
||||
close();
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetPosition
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetPosition") == 0) {
|
||||
stack->correctParams(1);
|
||||
if (_mode == 0) {
|
||||
script->runtimeError("File.%s: File is not open", name);
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
int pos = stack->pop()->getInt();
|
||||
stack->pushBool(setPos(pos));
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Delete
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Delete") == 0) {
|
||||
stack->correctParams(0);
|
||||
close();
|
||||
stack->pushBool(sfmFileRemove(_filename));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Copy
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Copy") == 0) {
|
||||
stack->correctParams(2);
|
||||
/* const char *dest = */ stack->pop()->getString();
|
||||
/* bool overwrite = */ stack->pop()->getBool(true);
|
||||
|
||||
// Known game that need this:
|
||||
// * Space Madness (to copy bonus wallpapers from data.dcp to /saves/ folder)
|
||||
// * games by Rootfix intertainment (to save temporary screenshot as savegame screenshot)
|
||||
warning("SXFile-Method: Copy not supported");
|
||||
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadLine
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadLine") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (!_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open in text mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
uint32 bufSize = FILE_BUFFER_SIZE;
|
||||
byte *buf = (byte *)malloc(bufSize);
|
||||
uint32 counter = 0;
|
||||
byte b;
|
||||
bool foundNewLine = false;
|
||||
bool ret = STATUS_FAILED;
|
||||
do {
|
||||
ret = _readFile->read(&b, 1);
|
||||
if (ret != 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (counter > bufSize) {
|
||||
buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
|
||||
bufSize += FILE_BUFFER_SIZE;
|
||||
}
|
||||
if (b == '\n') {
|
||||
buf[counter] = '\0';
|
||||
foundNewLine = true;
|
||||
break;
|
||||
} else if (b == 0x0D) {
|
||||
continue;
|
||||
} else {
|
||||
buf[counter] = b;
|
||||
counter++;
|
||||
}
|
||||
} while (DID_SUCCEED(ret));
|
||||
|
||||
if (counter > bufSize) {
|
||||
buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
|
||||
bufSize += FILE_BUFFER_SIZE;
|
||||
}
|
||||
buf[counter] = '\0';
|
||||
|
||||
if (!foundNewLine && counter == 0) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushString((char *)buf);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadText
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadText") == 0) {
|
||||
stack->correctParams(1);
|
||||
int textLen = stack->pop()->getInt();
|
||||
|
||||
if (!_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open in text mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
uint32 bufSize = FILE_BUFFER_SIZE;
|
||||
byte *buf = (byte *)malloc(bufSize);
|
||||
uint32 counter = 0;
|
||||
byte b;
|
||||
|
||||
bool ret = STATUS_FAILED;
|
||||
while (counter < (uint32)textLen) {
|
||||
ret = _readFile->read(&b, 1);
|
||||
if (ret != 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (counter > bufSize) {
|
||||
buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
|
||||
bufSize += FILE_BUFFER_SIZE;
|
||||
}
|
||||
if (b == 0x0D) {
|
||||
continue;
|
||||
} else {
|
||||
buf[counter] = b;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter > bufSize) {
|
||||
buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
|
||||
bufSize += FILE_BUFFER_SIZE;
|
||||
}
|
||||
buf[counter] = '\0';
|
||||
|
||||
if (textLen > 0 && counter == 0) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushString((char *)buf);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteLine / WriteText
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteLine") == 0 || strcmp(name, "WriteText") == 0) {
|
||||
stack->correctParams(1);
|
||||
const char *line = stack->pop()->getString();
|
||||
if (!_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in text mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
Common::String writeLine;
|
||||
if (strcmp(name, "WriteLine") == 0) {
|
||||
writeLine = Common::String::format("%s\n", line);
|
||||
} else {
|
||||
writeLine = Common::String::format("%s", line);
|
||||
}
|
||||
_writeFile->writeString(writeLine);
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadBool
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadBool") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
byte val;
|
||||
if (_readFile->read(&val, sizeof(byte))) {
|
||||
stack->pushBool(val != 0);
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadByte
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadByte") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
byte val = _readFile->readByte();
|
||||
if (!_readFile->err()) {
|
||||
stack->pushInt(val);
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadShort
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadShort") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
int16 val = _readFile->readSint16LE();
|
||||
if (!_readFile->err()) {
|
||||
stack->pushInt(65536 + val);
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadInt / ReadLong
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadInt") == 0 || strcmp(name, "ReadLong") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
int32 val = _readFile->readSint32LE();
|
||||
if (!_readFile->err()) {
|
||||
stack->pushInt(val);
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadFloat
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadFloat") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
float val = _readFile->readFloatLE();
|
||||
if (!_readFile->err()) {
|
||||
stack->pushFloat(val);
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadDouble
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadDouble") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
double val = _readFile->readDoubleLE();
|
||||
if (!_readFile->err()) {
|
||||
stack->pushFloat(val);
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ReadString
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ReadString") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_textMode || !_readFile) {
|
||||
script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
uint32 size = _readFile->readUint32LE();
|
||||
if (!_readFile->err()) {
|
||||
byte *str = new byte[size + 1];
|
||||
if (str) {
|
||||
if (_readFile->read(str, size) == size) {
|
||||
str[size] = '\0';
|
||||
stack->pushString((char *)str);
|
||||
}
|
||||
delete[] str;
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteBool
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteBool") == 0) {
|
||||
stack->correctParams(1);
|
||||
bool val = stack->pop()->getBool();
|
||||
|
||||
if (_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
_writeFile->writeByte(val);
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteByte
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteByte") == 0) {
|
||||
stack->correctParams(1);
|
||||
byte val = stack->pop()->getInt();
|
||||
|
||||
if (_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
_writeFile->writeByte(val);
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteShort
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteShort") == 0) {
|
||||
stack->correctParams(1);
|
||||
int16 val = stack->pop()->getInt();
|
||||
|
||||
if (_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
_writeFile->writeSint16LE(val);
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteInt / WriteLong
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteInt") == 0 || strcmp(name, "WriteLong") == 0) {
|
||||
stack->correctParams(1);
|
||||
int32 val = stack->pop()->getInt();
|
||||
|
||||
if (_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
_writeFile->writeSint32LE(val);
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteFloat
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteFloat") == 0) {
|
||||
stack->correctParams(1);
|
||||
float val = stack->pop()->getFloat();
|
||||
|
||||
if (_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
uint32 *ptr = (uint32 *)&val;
|
||||
_writeFile->writeUint32LE(*ptr);
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteDouble
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteDouble") == 0) {
|
||||
stack->correctParams(1);
|
||||
double val = stack->pop()->getFloat();
|
||||
|
||||
if (_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
_writeFile->writeDoubleLE(val);
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WriteString
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "WriteString") == 0) {
|
||||
stack->correctParams(1);
|
||||
const char *val = stack->pop()->getString();
|
||||
|
||||
if (_textMode || !_writeFile) {
|
||||
script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
|
||||
stack->pushBool(false);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
uint32 size = strlen(val);
|
||||
_writeFile->writeUint32LE(size);
|
||||
_writeFile->writeString(val);
|
||||
|
||||
stack->pushBool(true);
|
||||
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return BaseScriptable::scCallMethod(script, stack, thisStack, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXFile::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("file");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Filename (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Filename") == 0) {
|
||||
_scValue->setString(_filename);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Position (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Position") == 0) {
|
||||
_scValue->setInt(getPos());
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Length (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Length") == 0) {
|
||||
_scValue->setInt(getLength());
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TextMode (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "TextMode") == 0) {
|
||||
_scValue->setBool(_textMode);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AccessMode (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "AccessMode") == 0) {
|
||||
_scValue->setInt(_mode);
|
||||
return _scValue;
|
||||
} else {
|
||||
return BaseScriptable::scGetProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXFile::scSetProperty(const char *name, ScValue *value) {
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Length
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Length")==0) {
|
||||
int origLength = _length;
|
||||
_length = MAX(value->getInt(0), 0);
|
||||
|
||||
char propName[20];
|
||||
if (_length < OrigLength) {
|
||||
for(int i=_length; i<OrigLength; i++) {
|
||||
Common::sprintf_s(PropName, "%d", i);
|
||||
_values->DeleteProp(PropName);
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
else*/ return BaseScriptable::scSetProperty(name, value);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint32 SXFile::getPos() {
|
||||
if (_mode == 1 && _readFile) {
|
||||
return _readFile->pos();
|
||||
} else if ((_mode == 2 || _mode == 3) && _writeFile) {
|
||||
error("SXFile - getPos for WriteFile not supported");
|
||||
return 0;
|
||||
// return ftell((FILE *)_writeFile);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXFile::setPos(uint32 pos, int whence) {
|
||||
if (_mode == 1 && _readFile) {
|
||||
return _readFile->seek(pos, whence);
|
||||
} else if ((_mode == 2 || _mode == 3) && _writeFile) {
|
||||
if (BaseEngine::instance().getGameId() != "royalmahjong") {
|
||||
error("SXFile - seeking in WriteFile not supported");
|
||||
}
|
||||
return false;
|
||||
// return fseek((FILE *)_writeFile, pos, (int)origin) == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint32 SXFile::getLength() {
|
||||
if (_mode == 1 && _readFile) {
|
||||
return _readFile->size();
|
||||
} else if ((_mode == 2 || _mode == 3) && _writeFile) {
|
||||
error("SXFile - reading length for WriteFile not supported");
|
||||
return 0;
|
||||
/*
|
||||
uint32 currentPos = ftell((FILE *)_writeFile);
|
||||
fseek((FILE *)_writeFile, 0, SEEK_END);
|
||||
int ret = ftell((FILE *)_writeFile);
|
||||
fseek((FILE *)_writeFile, CurrentPos, SEEK_SET);
|
||||
return Ret;*/
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXFile::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseScriptable::persist(persistMgr);
|
||||
|
||||
persistMgr->transferCharPtr(TMEMBER(_filename));
|
||||
persistMgr->transferSint32(TMEMBER(_mode));
|
||||
persistMgr->transferBool(TMEMBER(_textMode));
|
||||
|
||||
uint32 pos = 0;
|
||||
if (persistMgr->getIsSaving()) {
|
||||
pos = getPos();
|
||||
persistMgr->transferUint32(TMEMBER(pos));
|
||||
} else {
|
||||
persistMgr->transferUint32(TMEMBER(pos));
|
||||
|
||||
// try to re-open file if needed
|
||||
_writeFile = nullptr;
|
||||
_readFile = nullptr;
|
||||
|
||||
if (_mode != 0) {
|
||||
// open for reading
|
||||
if (_mode == 1) {
|
||||
_readFile = _game->_fileManager->openFile(_filename);
|
||||
if (!_readFile) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
// open for writing / appending
|
||||
else {
|
||||
if (_textMode) {
|
||||
if (_mode == 2) {
|
||||
_writeFile = openForWrite(_filename, false);
|
||||
} else {
|
||||
_writeFile = openForAppend(_filename, false);
|
||||
}
|
||||
} else {
|
||||
if (_mode == 2) {
|
||||
_writeFile = openForWrite(_filename, true);
|
||||
} else {
|
||||
_writeFile = openForAppend(_filename, true);
|
||||
}
|
||||
}
|
||||
if (_writeFile) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
setPos(pos);
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
Common::WriteStream *SXFile::openForWrite(const Common::String &filename, bool binary) {
|
||||
return BaseFileManager::getEngineInstance()->openFileForWrite(_filename);
|
||||
}
|
||||
|
||||
// Should replace fopen(..., "ab+") and fopen(..., "a+")
|
||||
Common::WriteStream *SXFile::openForAppend(const Common::String &filename, bool binary) {
|
||||
warning("SXFile::openForAppend - WriteFiles with limited support as non-append mode");
|
||||
return BaseFileManager::getEngineInstance()->openFileForWrite(_filename);
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
65
engines/wintermute/base/scriptables/script_ext_file.h
Normal file
65
engines/wintermute/base/scriptables/script_ext_file.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTES_SXFILE_H
|
||||
#define WINTERMUTES_SXFILE_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXFile : public BaseScriptable {
|
||||
public:
|
||||
DECLARE_PERSISTENT(SXFile, BaseScriptable)
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
SXFile(BaseGame *inGame, ScStack *stack);
|
||||
~SXFile() override;
|
||||
|
||||
private:
|
||||
Common::SeekableReadStream *_readFile;
|
||||
Common::WriteStream *_writeFile;
|
||||
int32 _mode; // 0..none, 1..read, 2..write, 3..append
|
||||
bool _textMode;
|
||||
void close();
|
||||
void cleanup();
|
||||
uint32 getPos();
|
||||
uint32 getLength();
|
||||
bool setPos(uint32 pos, int whence = SEEK_SET);
|
||||
char *_filename;
|
||||
|
||||
Common::WriteStream *openForWrite(const Common::String &filename, bool binary);
|
||||
Common::WriteStream *openForAppend(const Common::String &filename, bool binary);
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
290
engines/wintermute/base/scriptables/script_ext_math.cpp
Normal file
290
engines/wintermute/base/scriptables/script_ext_math.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/scriptables/script_ext_math.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/persistent.h"
|
||||
#include "math/utils.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXMath, true)
|
||||
|
||||
BaseScriptable *makeSXMath(BaseGame *inGame) {
|
||||
return new SXMath(inGame);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXMath::SXMath(BaseGame *inGame) : BaseScriptable(inGame) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXMath::~SXMath() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXMath::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Abs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Abs") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(fabs(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Acos
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Acos") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(acos(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Asin
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Asin") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(asin(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Atan
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Atan") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(atan(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Atan2
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Atan2") == 0) {
|
||||
stack->correctParams(2);
|
||||
double y = stack->pop()->getFloat();
|
||||
double x = stack->pop()->getFloat();
|
||||
stack->pushFloat(atan2(y, x));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Ceil
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Ceil") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(ceil(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Cos
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Cos") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(cos(degreeToRadian(stack->pop()->getFloat())));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Cosh
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Cosh") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(cosh(degreeToRadian(stack->pop()->getFloat())));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Exp
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Exp") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(exp(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Floor
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Floor") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(floor(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Log
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Log") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(log(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Log10
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Log10") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(log10(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Pow
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Pow") == 0) {
|
||||
stack->correctParams(2);
|
||||
double x = stack->pop()->getFloat();
|
||||
double y = stack->pop()->getFloat();
|
||||
|
||||
stack->pushFloat(pow(x, y));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sin
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Sin") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(sin(degreeToRadian(stack->pop()->getFloat())));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sinh
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Sinh") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(sinh(degreeToRadian(stack->pop()->getFloat())));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Tan
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Tan") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(tan(degreeToRadian(stack->pop()->getFloat())));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Tanh
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Tanh") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(tanh(degreeToRadian(stack->pop()->getFloat())));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sqrt
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Sqrt") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(sqrt(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DegToRad
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DegToRad") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(degreeToRadian(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RadToDeg
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "RadToDeg") == 0) {
|
||||
stack->correctParams(1);
|
||||
stack->pushFloat(radianToDegree(stack->pop()->getFloat()));
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXMath::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("math");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PI
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "PI") == 0) {
|
||||
_scValue->setFloat(M_PI);
|
||||
return _scValue;
|
||||
} else {
|
||||
return _scValue;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
double SXMath::degreeToRadian(double value) {
|
||||
return value * (M_PI / 180.0f);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
double SXMath::radianToDegree(double value) {
|
||||
return value * (180.0f / M_PI);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXMath::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseScriptable::persist(persistMgr);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
52
engines/wintermute/base/scriptables/script_ext_math.h
Normal file
52
engines/wintermute/base/scriptables/script_ext_math.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SXMATH_H
|
||||
#define WINTERMUTE_SXMATH_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXMath : public BaseScriptable {
|
||||
public:
|
||||
DECLARE_PERSISTENT(SXMath, BaseScriptable)
|
||||
SXMath(BaseGame *inGame);
|
||||
~SXMath() override;
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
|
||||
private:
|
||||
double degreeToRadian(double value);
|
||||
double radianToDegree(double value);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
529
engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
Normal file
529
engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
Normal file
@@ -0,0 +1,529 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_mem_buffer.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXMemBuffer, false)
|
||||
|
||||
BaseScriptable *makeSXMemBuffer(BaseGame *inGame, ScStack *stack) {
|
||||
return new SXMemBuffer(inGame, stack);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXMemBuffer::SXMemBuffer(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
|
||||
stack->correctParams(1);
|
||||
_buffer = nullptr;
|
||||
_size = 0;
|
||||
|
||||
int newSize = stack->pop()->getInt();
|
||||
resize(MAX(0, newSize));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXMemBuffer::SXMemBuffer(BaseGame *inGame, void *buffer) : BaseScriptable(inGame) {
|
||||
_size = 0;
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXMemBuffer::~SXMemBuffer() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void *SXMemBuffer::scToMemBuffer() {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SXMemBuffer::cleanup() {
|
||||
if (_size) {
|
||||
free(_buffer);
|
||||
}
|
||||
_buffer = nullptr;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXMemBuffer::resize(int newSize) {
|
||||
int oldSize = _size;
|
||||
|
||||
if (_size == 0) {
|
||||
_buffer = malloc(newSize);
|
||||
if (_buffer) {
|
||||
_size = newSize;
|
||||
}
|
||||
} else {
|
||||
void *newBuf = realloc(_buffer, newSize);
|
||||
if (!newBuf) {
|
||||
if (newSize == 0) {
|
||||
_buffer = newBuf;
|
||||
_size = newSize;
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
} else {
|
||||
_buffer = newBuf;
|
||||
_size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (_buffer && _size > oldSize) {
|
||||
memset((byte *)_buffer + oldSize, 0, _size - oldSize);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXMemBuffer::checkBounds(ScScript *script, int start, int length) {
|
||||
if (_buffer == nullptr) {
|
||||
script->runtimeError("Cannot use Set/Get methods on an uninitialized memory buffer");
|
||||
return false;
|
||||
}
|
||||
if (_size == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (start < 0 || length == 0 || start + length > _size) {
|
||||
script->runtimeError("Set/Get method call is out of bounds");
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *SXMemBuffer::scToString() {
|
||||
return "[membuffer object]";
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXMemBuffer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetSize
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "SetSize") == 0) {
|
||||
stack->correctParams(1);
|
||||
int newSize = stack->pop()->getInt();
|
||||
newSize = MAX(0, newSize);
|
||||
if (DID_SUCCEED(resize(newSize))) {
|
||||
stack->pushBool(true);
|
||||
} else {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetBool
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetBool") == 0) {
|
||||
stack->correctParams(1);
|
||||
int start = stack->pop()->getInt();
|
||||
if (!checkBounds(script, start, sizeof(byte))) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushBool(*((byte *)_buffer + start) != 0);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetByte
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetByte") == 0) {
|
||||
stack->correctParams(1);
|
||||
int start = stack->pop()->getInt();
|
||||
if (!checkBounds(script, start, sizeof(byte))) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushInt(*(byte *)((byte *)_buffer + start));
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetShort
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetShort") == 0) {
|
||||
stack->correctParams(1);
|
||||
int start = stack->pop()->getInt();
|
||||
if (!checkBounds(script, start, sizeof(short))) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushInt(65536 + * (short *)((byte *)_buffer + start));
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetInt / GetLong
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetInt") == 0 || strcmp(name, "GetLong") == 0) {
|
||||
stack->correctParams(1);
|
||||
int start = stack->pop()->getInt();
|
||||
if (!checkBounds(script, start, sizeof(int))) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushInt(*(int *)((byte *)_buffer + start));
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetFloat
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetFloat") == 0) {
|
||||
stack->correctParams(1);
|
||||
int start = stack->pop()->getInt();
|
||||
if (!checkBounds(script, start, sizeof(float))) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushFloat(*(float *)((byte *)_buffer + start));
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetDouble
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetDouble") == 0) {
|
||||
stack->correctParams(1);
|
||||
int start = stack->pop()->getInt();
|
||||
if (!checkBounds(script, start, sizeof(double))) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushFloat(*(double *)((byte *)_buffer + start));
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetString
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetString") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
int length = stack->pop()->getInt();
|
||||
|
||||
// find end of string
|
||||
if (length == 0 && start >= 0 && start < _size) {
|
||||
for (int i = start; i < _size; i++) {
|
||||
if (((char *)_buffer)[i] == '\0') {
|
||||
length = i - start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkBounds(script, start, length)) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
char *str = new char[length + 1];
|
||||
strncpy(str, (const char *)_buffer + start, length);
|
||||
str[length] = '\0';
|
||||
stack->pushString(str);
|
||||
delete[] str;
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetPointer
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetPointer") == 0) {
|
||||
stack->correctParams(1);
|
||||
int start = stack->pop()->getInt();
|
||||
if (!checkBounds(script, start, sizeof(void *))) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
void *pointer = *(void **)((byte *)_buffer + start);
|
||||
SXMemBuffer *buf = new SXMemBuffer(_game, pointer);
|
||||
stack->pushNative(buf, false);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetBool
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetBool") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
bool val = stack->pop()->getBool();
|
||||
|
||||
if (!checkBounds(script, start, sizeof(byte))) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
*((byte *)_buffer + start) = (byte)val;
|
||||
stack->pushBool(true);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetByte
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetByte") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
byte val = (byte)stack->pop()->getInt();
|
||||
|
||||
if (!checkBounds(script, start, sizeof(byte))) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
*(byte *)((byte *)_buffer + start) = val;
|
||||
stack->pushBool(true);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetShort
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetShort") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
short val = (short)stack->pop()->getInt();
|
||||
|
||||
if (!checkBounds(script, start, sizeof(short))) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
*(short *)((byte *)_buffer + start) = val;
|
||||
stack->pushBool(true);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetInt / SetLong
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetInt") == 0 || strcmp(name, "SetLong") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
int val = stack->pop()->getInt();
|
||||
|
||||
if (!checkBounds(script, start, sizeof(int))) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
*(int *)((byte *)_buffer + start) = val;
|
||||
stack->pushBool(true);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetFloat
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetFloat") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
float val = (float)stack->pop()->getFloat();
|
||||
|
||||
if (!checkBounds(script, start, sizeof(float))) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
*(float *)((byte *)_buffer + start) = val;
|
||||
stack->pushBool(true);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetDouble
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetDouble") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
double val = stack->pop()->getFloat();
|
||||
|
||||
if (!checkBounds(script, start, sizeof(double))) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
*(double *)((byte *)_buffer + start) = val;
|
||||
stack->pushBool(true);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetString
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetString") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
const char *val = stack->pop()->getString();
|
||||
|
||||
if (!checkBounds(script, start, strlen(val) + 1)) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
memcpy((byte *)_buffer + start, val, strlen(val) + 1);
|
||||
stack->pushBool(true);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetPointer
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetPointer") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
/* ScValue *val = */ stack->pop();
|
||||
|
||||
if (!checkBounds(script, start, sizeof(void *))) {
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
/*
|
||||
int pointer = (int)Val->getMemBuffer();
|
||||
memcpy((byte *)_buffer+Start, &Pointer, sizeof(void*));
|
||||
stack->pushBool(true);
|
||||
*/
|
||||
// TODO: fix
|
||||
debug(3, "SXMemBuffer::ScCallMethod - SetPointer Bounds FIXME");
|
||||
stack->pushBool(false);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DEBUG_Dump
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "DEBUG_Dump") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_buffer && _size) {
|
||||
warning("SXMemBuffer::ScCallMethod - DEBUG_Dump");
|
||||
Common::DumpFile f;
|
||||
f.open("buffer.bin");
|
||||
f.write(_buffer, _size);
|
||||
f.close();
|
||||
}
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXMemBuffer::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("membuffer");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Size (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Size") == 0) {
|
||||
_scValue->setInt(_size);
|
||||
return _scValue;
|
||||
} else {
|
||||
return BaseScriptable::scGetProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXMemBuffer::scSetProperty(const char *name, ScValue *value) {
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Length
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Length")==0) {
|
||||
int origLength = _length;
|
||||
_length = MAX(value->getInt(0), 0);
|
||||
|
||||
char propName[20];
|
||||
if (_length < origLength) {
|
||||
for(int i=_length; i < origLength; i++) {
|
||||
Common::sprintf_s(propName, "%d", i);
|
||||
_values->DeleteProp(propName);
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
else*/ return BaseScriptable::scSetProperty(name, value);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXMemBuffer::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseScriptable::persist(persistMgr);
|
||||
|
||||
persistMgr->transferSint32(TMEMBER(_size));
|
||||
|
||||
if (persistMgr->getIsSaving()) {
|
||||
if (_size > 0) {
|
||||
persistMgr->putBytes((byte *)_buffer, _size);
|
||||
}
|
||||
} else {
|
||||
if (_size > 0) {
|
||||
_buffer = malloc(_size);
|
||||
persistMgr->getBytes((byte *)_buffer, _size);
|
||||
} else {
|
||||
_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int SXMemBuffer::scCompare(BaseScriptable *val) {
|
||||
if (_buffer == val->scToMemBuffer()) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
59
engines/wintermute/base/scriptables/script_ext_mem_buffer.h
Normal file
59
engines/wintermute/base/scriptables/script_ext_mem_buffer.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SXMEMBUFFER_H
|
||||
#define WINTERMUTE_SXMEMBUFFER_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXMemBuffer : public BaseScriptable {
|
||||
public:
|
||||
int scCompare(BaseScriptable *val) override;
|
||||
DECLARE_PERSISTENT(SXMemBuffer, BaseScriptable)
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
SXMemBuffer(BaseGame *inGame, ScStack *stack);
|
||||
SXMemBuffer(BaseGame *inGame, void *buffer);
|
||||
~SXMemBuffer() override;
|
||||
void *scToMemBuffer() override;
|
||||
int32 _size;
|
||||
|
||||
private:
|
||||
bool resize(int newSize);
|
||||
void *_buffer;
|
||||
void cleanup();
|
||||
bool checkBounds(ScScript *script, int start, int length);
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
66
engines/wintermute/base/scriptables/script_ext_object.cpp
Normal file
66
engines/wintermute/base/scriptables/script_ext_object.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/scriptables/script_ext_object.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXObject, false)
|
||||
|
||||
BaseScriptable *makeSXObject(BaseGame *inGame, ScStack *stack) {
|
||||
return new SXObject(inGame, stack);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXObject::SXObject(BaseGame *inGame, ScStack *stack) : BaseObject(inGame) {
|
||||
int numParams = stack->pop()->getInt(0);
|
||||
for (int i = 0; i < numParams; i++) {
|
||||
addScript(stack->pop()->getString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXObject::~SXObject() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXObject::persist(BasePersistenceManager *persistMgr) {
|
||||
BaseObject::persist(persistMgr);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
45
engines/wintermute/base/scriptables/script_ext_object.h
Normal file
45
engines/wintermute/base/scriptables/script_ext_object.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SXOBJECT_H
|
||||
#define WINTERMUTE_SXOBJECT_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base_object.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXObject : public BaseObject {
|
||||
public:
|
||||
DECLARE_PERSISTENT(SXObject, BaseObject)
|
||||
SXObject(BaseGame *inGame, ScStack *stack);
|
||||
~SXObject() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
443
engines/wintermute/base/scriptables/script_ext_string.cpp
Normal file
443
engines/wintermute/base/scriptables/script_ext_string.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/utils/utils.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_string.h"
|
||||
#include "engines/wintermute/base/scriptables/script_ext_array.h"
|
||||
#include "engines/wintermute/utils/string_util.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/tokenizer.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(SXString, false)
|
||||
|
||||
BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack) {
|
||||
return new SXString(inGame, stack);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXString::SXString(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
|
||||
_string = nullptr;
|
||||
_capacity = 0;
|
||||
|
||||
stack->correctParams(1);
|
||||
ScValue *val = stack->pop();
|
||||
|
||||
if (val->isInt()) {
|
||||
_capacity = MAX(0, val->getInt());
|
||||
if (_capacity > 0) {
|
||||
_string = new char[_capacity]();
|
||||
memset(_string, 0, _capacity);
|
||||
}
|
||||
} else {
|
||||
setStringVal(val->getString());
|
||||
}
|
||||
|
||||
if (_capacity == 0) {
|
||||
setStringVal("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SXString::~SXString() {
|
||||
if (_string) {
|
||||
delete[] _string;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SXString::setStringVal(const char *val) {
|
||||
int len = strlen(val);
|
||||
if (len >= _capacity) {
|
||||
_capacity = len + 1;
|
||||
SAFE_DELETE_ARRAY(_string);
|
||||
_string = new char[_capacity]();
|
||||
memset(_string, 0, _capacity);
|
||||
}
|
||||
Common::strcpy_s(_string, _capacity, val);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *SXString::scToString() {
|
||||
if (_string) {
|
||||
return _string;
|
||||
} else {
|
||||
return "[null string]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SXString::scSetString(const char *val) {
|
||||
setStringVal(val);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Substring
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Substring") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
int end = stack->pop()->getInt();
|
||||
|
||||
if (end < start) {
|
||||
BaseUtils::swap(&start, &end);
|
||||
}
|
||||
|
||||
//try {
|
||||
WideString str;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
str = StringUtil::utf8ToWide(_string);
|
||||
} else {
|
||||
str = StringUtil::ansiToWide(_string);
|
||||
}
|
||||
|
||||
WideString subStr = str.substr(start, end - start + 1);
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
|
||||
} else {
|
||||
stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
|
||||
}
|
||||
// } catch (std::exception &) {
|
||||
// stack->pushNULL();
|
||||
// }
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Substr
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Substr") == 0) {
|
||||
stack->correctParams(2);
|
||||
int start = stack->pop()->getInt();
|
||||
|
||||
ScValue *val = stack->pop();
|
||||
int len = val->getInt();
|
||||
|
||||
if (!val->isNULL() && len <= 0) {
|
||||
stack->pushString("");
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
if (val->isNULL()) {
|
||||
len = strlen(_string) - start;
|
||||
}
|
||||
|
||||
// try {
|
||||
WideString str;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
str = StringUtil::utf8ToWide(_string);
|
||||
} else {
|
||||
str = StringUtil::ansiToWide(_string);
|
||||
}
|
||||
|
||||
WideString subStr = str.substr(start, len);
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
|
||||
} else {
|
||||
stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
|
||||
}
|
||||
// } catch (std::exception &) {
|
||||
// stack->pushNULL();
|
||||
// }
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ToUpperCase
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ToUpperCase") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
WideString str;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
str = StringUtil::utf8ToWide(_string);
|
||||
} else {
|
||||
str = StringUtil::ansiToWide(_string);
|
||||
}
|
||||
|
||||
str.toUppercase();
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
stack->pushString(StringUtil::wideToUtf8(str).c_str());
|
||||
} else {
|
||||
stack->pushString(StringUtil::wideToAnsi(str).c_str());
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ToLowerCase
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ToLowerCase") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
WideString str;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
str = StringUtil::utf8ToWide(_string);
|
||||
} else {
|
||||
str = StringUtil::ansiToWide(_string);
|
||||
}
|
||||
|
||||
str.toLowercase();
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
stack->pushString(StringUtil::wideToUtf8(str).c_str());
|
||||
} else {
|
||||
stack->pushString(StringUtil::wideToAnsi(str).c_str());
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IndexOf
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "IndexOf") == 0) {
|
||||
stack->correctParams(2);
|
||||
|
||||
const char *strToFind = stack->pop()->getString();
|
||||
int index = stack->pop()->getInt();
|
||||
|
||||
WideString str;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
str = StringUtil::utf8ToWide(_string);
|
||||
} else {
|
||||
str = StringUtil::ansiToWide(_string);
|
||||
}
|
||||
|
||||
WideString toFind;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
toFind = StringUtil::utf8ToWide(strToFind);
|
||||
} else {
|
||||
toFind = StringUtil::ansiToWide(strToFind);
|
||||
}
|
||||
|
||||
int indexOf = StringUtil::indexOf(str, toFind, index);
|
||||
stack->pushInt(indexOf);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_HEROCRAFT
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// [HeroCraft] GetCharCode
|
||||
// Returns integer value of char at given position
|
||||
// Used at "Pole Chudes" only
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetCharCode") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
int index = stack->pop()->getInt();
|
||||
int result = 0;
|
||||
if (strlen(_string) > (uint32)index) {
|
||||
result = _string[index];
|
||||
}
|
||||
stack->pushInt(result);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Split
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Split") == 0) {
|
||||
stack->correctParams(1);
|
||||
ScValue *val = stack->pop();
|
||||
char separators[MAX_PATH_LENGTH] = ",";
|
||||
if (!val->isNULL()) {
|
||||
Common::strlcpy(separators, val->getString(), MAX_PATH_LENGTH);
|
||||
}
|
||||
|
||||
SXArray *array = new SXArray(_game);
|
||||
if (!array) {
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
WideString str;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
str = StringUtil::utf8ToWide(_string);
|
||||
} else {
|
||||
str = StringUtil::ansiToWide(_string);
|
||||
}
|
||||
|
||||
WideString delims;
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
delims = StringUtil::utf8ToWide(separators);
|
||||
} else {
|
||||
delims = StringUtil::ansiToWide(separators);
|
||||
}
|
||||
|
||||
Common::Array<WideString> parts;
|
||||
|
||||
uint32 start = 0;
|
||||
for(uint32 i = 0; i < str.size() + 1; i++) {
|
||||
// The [] operator doesn't allow access to the zero code terminator
|
||||
// (bug #6531)
|
||||
uint32 ch = (i == str.size()) ? '\0' : str[i];
|
||||
if (ch =='\0' || delims.contains(ch)) {
|
||||
if (i != start) {
|
||||
parts.push_back(str.substr(start, i - start));
|
||||
} else {
|
||||
parts.push_back(WideString());
|
||||
}
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (Common::Array<WideString>::iterator it = parts.begin(); it != parts.end(); ++it) {
|
||||
WideString &part = (*it);
|
||||
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
val = new ScValue(_game, StringUtil::wideToUtf8(part).c_str());
|
||||
} else {
|
||||
val = new ScValue(_game, StringUtil::wideToAnsi(part).c_str());
|
||||
}
|
||||
|
||||
array->push(val);
|
||||
SAFE_DELETE(val);
|
||||
}
|
||||
|
||||
stack->pushNative(array, false);
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *SXString::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("string");
|
||||
return _scValue;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Length (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Length") == 0) {
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
WideString wstr = StringUtil::utf8ToWide(_string);
|
||||
_scValue->setInt(wstr.size());
|
||||
} else {
|
||||
_scValue->setInt(strlen(_string));
|
||||
}
|
||||
|
||||
return _scValue;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Capacity
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Capacity") == 0) {
|
||||
_scValue->setInt(_capacity);
|
||||
return _scValue;
|
||||
} else {
|
||||
return _scValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXString::scSetProperty(const char *name, ScValue *value) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Capacity
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Capacity") == 0) {
|
||||
int32 newCap = (uint32)value->getInt();
|
||||
if (newCap < (int32)(strlen(_string) + 1)) {
|
||||
_game->LOG(0, "Warning: cannot lower string capacity");
|
||||
} else if (newCap != _capacity) {
|
||||
char *newStr = new char[newCap]();
|
||||
if (newStr) {
|
||||
Common::strcpy_s(newStr, newCap, _string);
|
||||
SAFE_DELETE_ARRAY(_string);
|
||||
_string = newStr;
|
||||
_capacity = newCap;
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SXString::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseScriptable::persist(persistMgr);
|
||||
|
||||
persistMgr->transferSint32(TMEMBER(_capacity));
|
||||
|
||||
if (persistMgr->getIsSaving()) {
|
||||
if (_capacity > 0) {
|
||||
persistMgr->putBytes((byte *)_string, _capacity);
|
||||
}
|
||||
} else {
|
||||
if (_capacity > 0) {
|
||||
_string = new char[_capacity];
|
||||
persistMgr->getBytes((byte *)_string, _capacity);
|
||||
} else {
|
||||
_string = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int SXString::scCompare(BaseScriptable *val) {
|
||||
return strcmp(_string, ((SXString *)val)->_string);
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
54
engines/wintermute/base/scriptables/script_ext_string.h
Normal file
54
engines/wintermute/base/scriptables/script_ext_string.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SXSTRING_H
|
||||
#define WINTERMUTE_SXSTRING_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base_scriptable.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class SXString : public BaseScriptable {
|
||||
public:
|
||||
int scCompare(BaseScriptable *val) override;
|
||||
DECLARE_PERSISTENT(SXString, BaseScriptable)
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
void scSetString(const char *val) override;
|
||||
const char *scToString() override;
|
||||
void setStringVal(const char *val);
|
||||
char *_string;
|
||||
SXString(BaseGame *inGame, ScStack *stack);
|
||||
~SXString() override;
|
||||
int32 _capacity;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
135
engines/wintermute/base/scriptables/script_opcodes.h
Normal file
135
engines/wintermute/base/scriptables/script_opcodes.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SCOPCODES_H
|
||||
#define WINTERMUTE_SCOPCODES_H
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
const uint32 foxtail_1_2_896_mapping[] = {
|
||||
II_CMP_LE,
|
||||
II_JMP,
|
||||
II_POP_REG1,
|
||||
II_PUSH_BOOL,
|
||||
II_MODULO,
|
||||
II_POP_EMPTY,
|
||||
II_CALL_BY_EXP,
|
||||
II_CMP_L,
|
||||
II_PUSH_FLOAT,
|
||||
II_NOT,
|
||||
II_PUSH_THIS,
|
||||
II_PUSH_BY_EXP,
|
||||
II_PUSH_THIS_FROM_STACK,
|
||||
II_CMP_G,
|
||||
II_DEF_GLOB_VAR,
|
||||
II_PUSH_STRING,
|
||||
II_PUSH_REG1,
|
||||
II_DEF_VAR,
|
||||
II_PUSH_VAR_THIS,
|
||||
II_RET_EVENT,
|
||||
II_PUSH_VAR_REF,
|
||||
II_CMP_NE,
|
||||
II_DBG_LINE,
|
||||
II_OR,
|
||||
II_POP_VAR,
|
||||
II_AND,
|
||||
II_EXTERNAL_CALL,
|
||||
II_CORRECT_STACK,
|
||||
II_RET,
|
||||
II_DIV,
|
||||
II_PUSH_VAR,
|
||||
II_SUB,
|
||||
II_CALL,
|
||||
II_CREATE_OBJECT,
|
||||
II_MUL,
|
||||
II_POP_BY_EXP,
|
||||
II_DEF_CONST_VAR,
|
||||
II_PUSH_NULL,
|
||||
II_JMP_FALSE,
|
||||
II_ADD,
|
||||
II_CMP_GE,
|
||||
II_CMP_STRICT_EQ,
|
||||
II_CMP_STRICT_NE,
|
||||
II_PUSH_INT,
|
||||
II_CMP_EQ,
|
||||
II_POP_THIS,
|
||||
II_SCOPE
|
||||
};
|
||||
|
||||
const uint32 foxtail_1_2_902_mapping[] = {
|
||||
II_CMP_L,
|
||||
II_CALL,
|
||||
II_DEF_GLOB_VAR,
|
||||
II_DBG_LINE,
|
||||
II_JMP_FALSE,
|
||||
II_CMP_STRICT_EQ,
|
||||
II_PUSH_FLOAT,
|
||||
II_CALL_BY_EXP,
|
||||
II_MODULO,
|
||||
II_PUSH_THIS,
|
||||
II_CMP_GE,
|
||||
II_PUSH_BOOL,
|
||||
II_PUSH_VAR,
|
||||
II_PUSH_VAR_REF,
|
||||
II_POP_BY_EXP,
|
||||
II_CMP_STRICT_NE,
|
||||
II_RET_EVENT,
|
||||
II_PUSH_BY_EXP,
|
||||
II_CORRECT_STACK,
|
||||
II_POP_VAR,
|
||||
II_CMP_G,
|
||||
II_PUSH_THIS_FROM_STACK,
|
||||
II_JMP,
|
||||
II_AND,
|
||||
II_CREATE_OBJECT,
|
||||
II_POP_REG1,
|
||||
II_PUSH_STRING,
|
||||
II_POP_EMPTY,
|
||||
II_DIV,
|
||||
II_ADD,
|
||||
II_RET,
|
||||
II_EXTERNAL_CALL,
|
||||
II_NOT,
|
||||
II_OR,
|
||||
II_SUB,
|
||||
II_PUSH_INT,
|
||||
II_DEF_VAR,
|
||||
II_SCOPE,
|
||||
II_CMP_EQ,
|
||||
II_MUL,
|
||||
II_POP_THIS,
|
||||
II_CMP_LE,
|
||||
II_PUSH_REG1,
|
||||
II_DEF_CONST_VAR,
|
||||
II_PUSH_NULL,
|
||||
II_CMP_NE,
|
||||
II_PUSH_VAR_THIS
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
191
engines/wintermute/base/scriptables/script_stack.cpp
Normal file
191
engines/wintermute/base/scriptables/script_stack.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(ScStack, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScStack::ScStack(BaseGame *inGame) : BaseClass(inGame) {
|
||||
_sP = -1;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScStack::~ScStack() {
|
||||
//_game->LOG(0, "STAT: Stack size: %d, SP=%d", _values.getSize(), _sP);
|
||||
|
||||
for (int32 i = 0; i < _values.getSize(); i++) {
|
||||
delete _values[i];
|
||||
}
|
||||
_values.removeAll();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *ScStack::pop() {
|
||||
if (_sP < 0) {
|
||||
_game->LOG(0, "Fatal: Stack underflow");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _values[_sP--];
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::push(ScValue *val) {
|
||||
_sP++;
|
||||
|
||||
if (_sP < _values.getSize()) {
|
||||
_values[_sP]->cleanup();
|
||||
_values[_sP]->copy(val);
|
||||
} else {
|
||||
ScValue *copyVal = new ScValue(_game);
|
||||
copyVal->copy(val);
|
||||
_values.add(copyVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *ScStack::getPushValue() {
|
||||
_sP++;
|
||||
|
||||
if (_sP >= _values.getSize()) {
|
||||
ScValue *val = new ScValue(_game);
|
||||
_values.add(val);
|
||||
}
|
||||
_values[_sP]->cleanup();
|
||||
return _values[_sP];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *ScStack::getTop() {
|
||||
if (_sP < 0 || _sP >= _values.getSize()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return _values[_sP];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *ScStack::getAt(int index) {
|
||||
index = _sP - index;
|
||||
if (index < 0 || index >= _values.getSize()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return _values[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::correctParams(uint32 expectedParams) {
|
||||
uint32 numParams = (uint32)pop()->getInt();
|
||||
|
||||
if (expectedParams < numParams) { // too many params
|
||||
while (expectedParams < numParams) {
|
||||
//pop();
|
||||
delete _values[_sP - expectedParams];
|
||||
_values.removeAt(_sP - expectedParams);
|
||||
numParams--;
|
||||
_sP--;
|
||||
}
|
||||
} else if (expectedParams > numParams) { // need more params
|
||||
while (expectedParams > numParams) {
|
||||
//push(nullVal);
|
||||
ScValue *nullVal = new ScValue(_game);
|
||||
nullVal->setNULL();
|
||||
_values.insertAt(_sP - numParams + 1, nullVal);
|
||||
numParams++;
|
||||
_sP++;
|
||||
|
||||
if (_values.getSize() > _sP + 1) {
|
||||
delete _values[_values.getSize() - 1];
|
||||
_values.removeAt(_values.getSize() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::pushNULL() {
|
||||
getPushValue()->setNULL();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::pushInt(int val) {
|
||||
getPushValue()->setInt(val);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::pushFloat(double val) {
|
||||
getPushValue()->setFloat(val);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::pushBool(bool val) {
|
||||
getPushValue()->setBool(val);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::pushString(const char *val) {
|
||||
getPushValue()->setString(val);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ScStack::pushNative(BaseScriptable *val, bool persistent) {
|
||||
getPushValue()->setNative(val, persistent);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool ScStack::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_game));
|
||||
|
||||
persistMgr->transferSint32(TMEMBER(_sP));
|
||||
_values.persist(persistMgr);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
65
engines/wintermute/base/scriptables/script_stack.h
Normal file
65
engines/wintermute/base/scriptables/script_stack.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SCSTACK_H
|
||||
#define WINTERMUTE_SCSTACK_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base.h"
|
||||
#include "engines/wintermute/coll_templ.h"
|
||||
#include "engines/wintermute/persistent.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class ScValue;
|
||||
class BaseScriptable;
|
||||
|
||||
class ScStack : public BaseClass {
|
||||
public:
|
||||
ScValue *getAt(int index);
|
||||
ScValue *getPushValue();
|
||||
DECLARE_PERSISTENT(ScStack, BaseClass)
|
||||
void pushNative(BaseScriptable *val, bool persistent);
|
||||
void pushString(const char *val);
|
||||
void pushBool(bool val);
|
||||
void pushInt(int val);
|
||||
void pushFloat(double val);
|
||||
void pushNULL();
|
||||
void correctParams(uint32 expectedParams);
|
||||
ScValue *getTop();
|
||||
void push(ScValue *val);
|
||||
ScValue *pop();
|
||||
ScStack(BaseGame *inGame);
|
||||
~ScStack() override;
|
||||
BaseArray<ScValue *> _values;
|
||||
int32 _sP;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
1018
engines/wintermute/base/scriptables/script_value.cpp
Normal file
1018
engines/wintermute/base/scriptables/script_value.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
engines/wintermute/base/scriptables/script_value.h
Normal file
110
engines/wintermute/base/scriptables/script_value.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_SCVALUE_H
|
||||
#define WINTERMUTE_SCVALUE_H
|
||||
|
||||
|
||||
#include "engines/wintermute/base/base.h"
|
||||
#include "engines/wintermute/persistent.h"
|
||||
#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class ScScript;
|
||||
class BaseScriptable;
|
||||
|
||||
class ScValue : public BaseClass {
|
||||
public:
|
||||
static int compare(ScValue *val1, ScValue *val2, bool enableFloatCompareWA);
|
||||
static int compareStrict(ScValue *val1, ScValue *val2, bool enableFloatCompareWA);
|
||||
TValType getTypeTolerant();
|
||||
void cleanup(bool ignoreNatives = false);
|
||||
DECLARE_PERSISTENT(ScValue, BaseClass)
|
||||
|
||||
bool _isConstVar;
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
void setValue(ScValue *val);
|
||||
bool _persistent;
|
||||
bool propExists(const char *name);
|
||||
void copy(ScValue *orig, bool copyWhole = false);
|
||||
void setStringVal(const char *val);
|
||||
TValType getType();
|
||||
bool getBool(bool defaultVal = false);
|
||||
int getInt(int defaultVal = 0);
|
||||
double getFloat(double defaultVal = 0.0f);
|
||||
const char *getString();
|
||||
void *getMemBuffer();
|
||||
BaseScriptable *getNative();
|
||||
bool deleteProp(const char *name);
|
||||
void deleteProps();
|
||||
void cleanProps(bool includingNatives);
|
||||
void setBool(bool val);
|
||||
void setInt(int val);
|
||||
void setFloat(double val);
|
||||
void setString(const char *val);
|
||||
void setString(const Common::String &val);
|
||||
void setNULL();
|
||||
void setNative(BaseScriptable *val, bool persistent = false);
|
||||
void setObject();
|
||||
void setReference(ScValue *val);
|
||||
bool isNULL();
|
||||
bool isNative();
|
||||
bool isString();
|
||||
bool isBool();
|
||||
bool isFloat();
|
||||
bool isInt();
|
||||
bool isObject();
|
||||
bool setProp(const char *name, ScValue *val, bool copyWhole = false, bool setAsConst = false);
|
||||
ScValue *getProp(const char *name);
|
||||
BaseScriptable *_valNative;
|
||||
ScValue *_valRef;
|
||||
bool _valBool;
|
||||
int32 _valInt;
|
||||
double _valFloat;
|
||||
char *_valString;
|
||||
TValType _type;
|
||||
ScValue(BaseGame *inGame);
|
||||
ScValue(BaseGame *inGame, bool val);
|
||||
ScValue(BaseGame *inGame, int32 val);
|
||||
ScValue(BaseGame *inGame, double val);
|
||||
ScValue(BaseGame *inGame, const char *val);
|
||||
~ScValue() override;
|
||||
Common::HashMap<Common::String, ScValue *> _valObject;
|
||||
Common::HashMap<Common::String, ScValue *>::iterator _valIter;
|
||||
|
||||
bool setProperty(const char *propName, int32 value);
|
||||
bool setProperty(const char *propName, const char *value);
|
||||
bool setProperty(const char *propName, double value);
|
||||
bool setProperty(const char *propName, bool value);
|
||||
bool setProperty(const char *propName);
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user