mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-12-19 17:37:42 -05:00
1479 lines
34 KiB
C++
1479 lines
34 KiB
C++
/*
|
|
AngelCode Scripting Library
|
|
Copyright (c) 2003-2009 Andreas Jonsson
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any
|
|
damages arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any
|
|
purpose, including commercial applications, and to alter it and
|
|
redistribute it freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you
|
|
must not claim that you wrote the original software. If you use
|
|
this software in a product, an acknowledgment in the product
|
|
documentation would be appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and
|
|
must not be misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source
|
|
distribution.
|
|
|
|
The original version of this library can be located at:
|
|
http://www.angelcode.com/angelscript/
|
|
|
|
Andreas Jonsson
|
|
andreas@angelcode.com
|
|
*/
|
|
|
|
|
|
//
|
|
// as_restore.cpp
|
|
//
|
|
// Functions for saving and restoring module bytecode
|
|
// asCRestore was originally written by Dennis Bollyn, dennis@gyrbo.be
|
|
|
|
#include "as_config.h"
|
|
#include "as_restore.h"
|
|
#include "as_bytecode.h"
|
|
#include "as_arrayobject.h"
|
|
|
|
BEGIN_AS_NAMESPACE
|
|
|
|
#define WRITE_NUM(N) stream->Write(&(N), sizeof(N))
|
|
#define READ_NUM(N) stream->Read(&(N), sizeof(N))
|
|
|
|
asCRestore::asCRestore(asCModule* _module, asIBinaryStream* _stream, asCScriptEngine* _engine)
|
|
: module(_module), stream(_stream), engine(_engine)
|
|
{
|
|
}
|
|
|
|
int asCRestore::Save()
|
|
{
|
|
unsigned long i, count;
|
|
|
|
// Store everything in the same order that the builder parses scripts
|
|
|
|
// Store enums
|
|
count = (asUINT)module->enumTypes.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; i++ )
|
|
{
|
|
WriteObjectTypeDeclaration(module->enumTypes[i], false);
|
|
WriteObjectTypeDeclaration(module->enumTypes[i], true);
|
|
}
|
|
|
|
// Store type declarations first
|
|
count = (asUINT)module->classTypes.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; i++ )
|
|
{
|
|
// Store only the name of the class/interface types
|
|
WriteObjectTypeDeclaration(module->classTypes[i], false);
|
|
}
|
|
|
|
// Now store all interface methods
|
|
for( i = 0; i < count; i++ )
|
|
{
|
|
if( module->classTypes[i]->IsInterface() )
|
|
WriteObjectTypeDeclaration(module->classTypes[i], true);
|
|
}
|
|
|
|
// Then store the class methods, properties, and behaviours
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
if( !module->classTypes[i]->IsInterface() )
|
|
WriteObjectTypeDeclaration(module->classTypes[i], true);
|
|
}
|
|
|
|
// Store typedefs
|
|
count = (asUINT)module->typeDefs.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; i++ )
|
|
{
|
|
WriteObjectTypeDeclaration(module->typeDefs[i], false);
|
|
WriteObjectTypeDeclaration(module->typeDefs[i], true);
|
|
}
|
|
|
|
// scriptGlobals[]
|
|
count = (asUINT)module->scriptGlobals.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
WriteGlobalProperty(module->scriptGlobals[i]);
|
|
|
|
// scriptFunctions[]
|
|
count = 0;
|
|
for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
|
|
if( module->scriptFunctions[i]->objectType == 0 )
|
|
count++;
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < module->scriptFunctions.GetLength(); ++i )
|
|
if( module->scriptFunctions[i]->objectType == 0 )
|
|
WriteFunction(module->scriptFunctions[i]);
|
|
|
|
// globalFunctions[]
|
|
count = (int)module->globalFunctions.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; i++ )
|
|
{
|
|
WriteFunction(module->globalFunctions[i]);
|
|
}
|
|
|
|
// bindInformations[]
|
|
count = (asUINT)module->bindInformations.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
WriteFunction(module->bindInformations[i]->importedFunctionSignature);
|
|
WriteString(&module->bindInformations[i]->importFromModule);
|
|
}
|
|
|
|
// usedTypes[]
|
|
count = (asUINT)usedTypes.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
WriteObjectType(usedTypes[i]);
|
|
}
|
|
|
|
// usedTypeIds[]
|
|
WriteUsedTypeIds();
|
|
|
|
// usedFunctions[]
|
|
WriteUsedFunctions();
|
|
|
|
// usedGlobalProperties[]
|
|
WriteUsedGlobalProps();
|
|
|
|
// usedStringConstants[]
|
|
WriteUsedStringConstants();
|
|
|
|
// TODO: Store script section names
|
|
|
|
return asSUCCESS;
|
|
}
|
|
|
|
int asCRestore::Restore()
|
|
{
|
|
// Before starting the load, make sure that
|
|
// any existing resources have been freed
|
|
module->InternalReset();
|
|
|
|
unsigned long i, count;
|
|
|
|
asCScriptFunction* func;
|
|
|
|
// Read enums
|
|
READ_NUM(count);
|
|
module->enumTypes.Allocate(count, 0);
|
|
for( i = 0; i < count; i++ )
|
|
{
|
|
asCObjectType *ot = asNEW(asCObjectType)(engine);
|
|
ReadObjectTypeDeclaration(ot, false);
|
|
engine->classTypes.PushLast(ot);
|
|
module->enumTypes.PushLast(ot);
|
|
ot->AddRef();
|
|
ReadObjectTypeDeclaration(ot, true);
|
|
}
|
|
|
|
// structTypes[]
|
|
// First restore the structure names, then the properties
|
|
READ_NUM(count);
|
|
module->classTypes.Allocate(count, 0);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
asCObjectType *ot = asNEW(asCObjectType)(engine);
|
|
ReadObjectTypeDeclaration(ot, false);
|
|
engine->classTypes.PushLast(ot);
|
|
module->classTypes.PushLast(ot);
|
|
ot->AddRef();
|
|
|
|
// Add script classes to the GC
|
|
if( (ot->GetFlags() & asOBJ_SCRIPT_OBJECT) && ot->GetSize() > 0 )
|
|
engine->gc.AddScriptObjectToGC(ot, &engine->objectTypeBehaviours);
|
|
}
|
|
|
|
// Read interface methods
|
|
for( i = 0; i < module->classTypes.GetLength(); i++ )
|
|
{
|
|
if( module->classTypes[i]->IsInterface() )
|
|
ReadObjectTypeDeclaration(module->classTypes[i], true);
|
|
}
|
|
|
|
module->ResolveInterfaceIds();
|
|
|
|
// Read class methods, properties, and behaviours
|
|
for( i = 0; i < module->classTypes.GetLength(); ++i )
|
|
{
|
|
if( !module->classTypes[i]->IsInterface() )
|
|
ReadObjectTypeDeclaration(module->classTypes[i], true);
|
|
}
|
|
|
|
// Read typedefs
|
|
READ_NUM(count);
|
|
module->typeDefs.Allocate(count, 0);
|
|
for( i = 0; i < count; i++ )
|
|
{
|
|
asCObjectType *ot = asNEW(asCObjectType)(engine);
|
|
ReadObjectTypeDeclaration(ot, false);
|
|
engine->classTypes.PushLast(ot);
|
|
module->typeDefs.PushLast(ot);
|
|
ot->AddRef();
|
|
ReadObjectTypeDeclaration(ot, true);
|
|
}
|
|
|
|
// scriptGlobals[]
|
|
READ_NUM(count);
|
|
module->scriptGlobals.Allocate(count, 0);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
ReadGlobalProperty();
|
|
}
|
|
|
|
// scriptFunctions[]
|
|
READ_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
func = ReadFunction();
|
|
}
|
|
|
|
// globalFunctions[]
|
|
READ_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
func = ReadFunction(false, false);
|
|
|
|
module->globalFunctions.PushLast(func);
|
|
func->AddRef();
|
|
}
|
|
|
|
// bindInformations[]
|
|
READ_NUM(count);
|
|
module->bindInformations.SetLength(count);
|
|
for(i=0;i<count;++i)
|
|
{
|
|
sBindInfo *info = asNEW(sBindInfo);
|
|
info->importedFunctionSignature = ReadFunction(false, false);
|
|
info->importedFunctionSignature->id = int(FUNC_IMPORTED + engine->importedFunctions.GetLength());
|
|
engine->importedFunctions.PushLast(info);
|
|
ReadString(&info->importFromModule);
|
|
info->boundFunctionId = -1;
|
|
module->bindInformations[i] = info;
|
|
}
|
|
|
|
// usedTypes[]
|
|
READ_NUM(count);
|
|
usedTypes.Allocate(count, 0);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
asCObjectType *ot = ReadObjectType();
|
|
usedTypes.PushLast(ot);
|
|
}
|
|
|
|
// usedTypeIds[]
|
|
ReadUsedTypeIds();
|
|
|
|
// usedFunctions[]
|
|
ReadUsedFunctions();
|
|
|
|
// usedGlobalProperties[]
|
|
ReadUsedGlobalProps();
|
|
|
|
// usedStringConstants[]
|
|
ReadUsedStringConstants();
|
|
|
|
for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
|
|
TranslateFunction(module->scriptFunctions[i]);
|
|
for( i = 0; i < module->scriptGlobals.GetLength(); i++ )
|
|
if( module->scriptGlobals[i]->initFunc )
|
|
TranslateFunction(module->scriptGlobals[i]->initFunc);
|
|
|
|
// Init system functions properly
|
|
engine->PrepareEngine();
|
|
|
|
// Add references for all functions
|
|
for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
|
|
module->scriptFunctions[i]->AddReferences();
|
|
for( i = 0; i < module->scriptGlobals.GetLength(); i++ )
|
|
if( module->scriptGlobals[i]->initFunc )
|
|
module->scriptGlobals[i]->initFunc->AddReferences();
|
|
|
|
module->CallInit();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int asCRestore::FindStringConstantIndex(int id)
|
|
{
|
|
for( asUINT i = 0; i < usedStringConstants.GetLength(); i++ )
|
|
if( usedStringConstants[i] == id )
|
|
return i;
|
|
|
|
usedStringConstants.PushLast(id);
|
|
return int(usedStringConstants.GetLength() - 1);
|
|
}
|
|
|
|
void asCRestore::WriteUsedStringConstants()
|
|
{
|
|
asUINT count = (asUINT)usedStringConstants.GetLength();
|
|
WRITE_NUM(count);
|
|
for( asUINT i = 0; i < count; ++i )
|
|
WriteString(engine->stringConstants[i]);
|
|
}
|
|
|
|
void asCRestore::ReadUsedStringConstants()
|
|
{
|
|
asCString str;
|
|
|
|
asUINT count;
|
|
READ_NUM(count);
|
|
usedStringConstants.SetLength(count);
|
|
for( asUINT i = 0; i < count; ++i )
|
|
{
|
|
ReadString(&str);
|
|
usedStringConstants[i] = engine->AddConstantString(str.AddressOf(), str.GetLength());
|
|
}
|
|
}
|
|
|
|
void asCRestore::WriteUsedFunctions()
|
|
{
|
|
asUINT count = (asUINT)usedFunctions.GetLength();
|
|
WRITE_NUM(count);
|
|
|
|
for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
|
|
{
|
|
char c;
|
|
|
|
// Write enough data to be able to uniquely identify the function upon load
|
|
|
|
// Is the function from the module or the application?
|
|
c = usedFunctions[n]->module ? 'm' : 'a';
|
|
WRITE_NUM(c);
|
|
|
|
WriteFunctionSignature(usedFunctions[n]);
|
|
}
|
|
}
|
|
|
|
void asCRestore::ReadUsedFunctions()
|
|
{
|
|
asUINT count;
|
|
READ_NUM(count);
|
|
usedFunctions.SetLength(count);
|
|
|
|
for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
|
|
{
|
|
char c;
|
|
|
|
// Read the data to be able to uniquely identify the function
|
|
|
|
// Is the function from the module or the application?
|
|
READ_NUM(c);
|
|
|
|
asCScriptFunction func(engine, c == 'm' ? module : 0, -1);
|
|
ReadFunctionSignature(&func);
|
|
|
|
// Find the correct function
|
|
if( c == 'm' )
|
|
{
|
|
for( asUINT i = 0; i < module->scriptFunctions.GetLength(); i++ )
|
|
{
|
|
asCScriptFunction *f = module->scriptFunctions[i];
|
|
if( !func.IsSignatureEqual(f) ||
|
|
func.objectType != f->objectType ||
|
|
func.funcType != f->funcType )
|
|
continue;
|
|
|
|
usedFunctions[n] = f;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++ )
|
|
{
|
|
asCScriptFunction *f = engine->scriptFunctions[i];
|
|
if( f == 0 ||
|
|
!func.IsSignatureEqual(f) ||
|
|
func.objectType != f->objectType )
|
|
continue;
|
|
|
|
usedFunctions[n] = f;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set the type to dummy so it won't try to release the id
|
|
func.funcType = -1;
|
|
}
|
|
}
|
|
|
|
void asCRestore::WriteFunctionSignature(asCScriptFunction *func)
|
|
{
|
|
asUINT i, count;
|
|
|
|
WriteString(&func->name);
|
|
WriteDataType(&func->returnType);
|
|
count = (asUINT)func->parameterTypes.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
WriteDataType(&func->parameterTypes[i]);
|
|
|
|
count = (asUINT)func->inOutFlags.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
WRITE_NUM(func->inOutFlags[i]);
|
|
|
|
WRITE_NUM(func->funcType);
|
|
|
|
WriteObjectType(func->objectType);
|
|
|
|
WRITE_NUM(func->isReadOnly);
|
|
}
|
|
|
|
void asCRestore::ReadFunctionSignature(asCScriptFunction *func)
|
|
{
|
|
int i, count;
|
|
asCDataType dt;
|
|
int num;
|
|
|
|
ReadString(&func->name);
|
|
ReadDataType(&func->returnType);
|
|
READ_NUM(count);
|
|
func->parameterTypes.Allocate(count, 0);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
ReadDataType(&dt);
|
|
func->parameterTypes.PushLast(dt);
|
|
}
|
|
|
|
READ_NUM(count);
|
|
func->inOutFlags.Allocate(count, 0);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
READ_NUM(num);
|
|
func->inOutFlags.PushLast(static_cast<asETypeModifiers>(num));
|
|
}
|
|
|
|
READ_NUM(func->funcType);
|
|
|
|
func->objectType = ReadObjectType();
|
|
|
|
READ_NUM(func->isReadOnly);
|
|
}
|
|
|
|
void asCRestore::WriteFunction(asCScriptFunction* func)
|
|
{
|
|
char c;
|
|
|
|
// If there is no function, then store a null char
|
|
if( func == 0 )
|
|
{
|
|
c = '\0';
|
|
WRITE_NUM(c);
|
|
return;
|
|
}
|
|
|
|
// First check if the function has been saved already
|
|
for( asUINT f = 0; f < savedFunctions.GetLength(); f++ )
|
|
{
|
|
if( savedFunctions[f] == func )
|
|
{
|
|
c = 'r';
|
|
WRITE_NUM(c);
|
|
WRITE_NUM(f);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Keep a reference to the function in the list
|
|
savedFunctions.PushLast(func);
|
|
|
|
c = 'f';
|
|
WRITE_NUM(c);
|
|
|
|
asUINT i, count;
|
|
|
|
WriteFunctionSignature(func);
|
|
|
|
count = (asUINT)func->byteCode.GetLength();
|
|
WRITE_NUM(count);
|
|
WriteByteCode(func->byteCode.AddressOf(), count);
|
|
|
|
count = (asUINT)func->objVariablePos.GetLength();
|
|
WRITE_NUM(count);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
WriteObjectType(func->objVariableTypes[i]);
|
|
WRITE_NUM(func->objVariablePos[i]);
|
|
}
|
|
|
|
WRITE_NUM(func->stackNeeded);
|
|
|
|
asUINT length = (asUINT)func->lineNumbers.GetLength();
|
|
WRITE_NUM(length);
|
|
for( i = 0; i < length; ++i )
|
|
WRITE_NUM(func->lineNumbers[i]);
|
|
|
|
WRITE_NUM(func->vfTableIdx);
|
|
|
|
// TODO: Write variables
|
|
|
|
// TODO: Store script section index
|
|
}
|
|
|
|
asCScriptFunction *asCRestore::ReadFunction(bool addToModule, bool addToEngine)
|
|
{
|
|
char c;
|
|
READ_NUM(c);
|
|
|
|
if( c == '\0' )
|
|
{
|
|
// There is no function, so return a null pointer
|
|
return 0;
|
|
}
|
|
|
|
if( c == 'r' )
|
|
{
|
|
// This is a reference to a previously saved function
|
|
int index;
|
|
READ_NUM(index);
|
|
|
|
return savedFunctions[index];
|
|
}
|
|
|
|
// Load the new function
|
|
asCScriptFunction *func = asNEW(asCScriptFunction)(engine,module,-1);
|
|
savedFunctions.PushLast(func);
|
|
|
|
int i, count;
|
|
asCDataType dt;
|
|
int num;
|
|
|
|
ReadFunctionSignature(func);
|
|
|
|
if( func->funcType == asFUNC_SCRIPT )
|
|
engine->gc.AddScriptObjectToGC(func, &engine->functionBehaviours);
|
|
|
|
func->id = engine->GetNextScriptFunctionId();
|
|
|
|
READ_NUM(count);
|
|
func->byteCode.Allocate(count, 0);
|
|
ReadByteCode(func->byteCode.AddressOf(), count);
|
|
func->byteCode.SetLength(count);
|
|
|
|
READ_NUM(count);
|
|
func->objVariablePos.Allocate(count, 0);
|
|
func->objVariableTypes.Allocate(count, 0);
|
|
for( i = 0; i < count; ++i )
|
|
{
|
|
func->objVariableTypes.PushLast(ReadObjectType());
|
|
READ_NUM(num);
|
|
func->objVariablePos.PushLast(num);
|
|
}
|
|
|
|
READ_NUM(func->stackNeeded);
|
|
|
|
int length;
|
|
READ_NUM(length);
|
|
func->lineNumbers.SetLength(length);
|
|
for( i = 0; i < length; ++i )
|
|
READ_NUM(func->lineNumbers[i]);
|
|
|
|
READ_NUM(func->vfTableIdx);
|
|
|
|
if( addToModule )
|
|
{
|
|
// The refCount is already 1
|
|
module->scriptFunctions.PushLast(func);
|
|
}
|
|
if( addToEngine )
|
|
engine->SetScriptFunction(func);
|
|
if( func->objectType )
|
|
func->ComputeSignatureId();
|
|
|
|
return func;
|
|
}
|
|
|
|
void asCRestore::WriteObjectTypeDeclaration(asCObjectType *ot, bool writeProperties)
|
|
{
|
|
if( !writeProperties )
|
|
{
|
|
// name
|
|
WriteString(&ot->name);
|
|
// size
|
|
int size = ot->size;
|
|
WRITE_NUM(size);
|
|
// flags
|
|
asDWORD flags = ot->flags;
|
|
WRITE_NUM(flags);
|
|
}
|
|
else
|
|
{
|
|
if( ot->flags & asOBJ_ENUM )
|
|
{
|
|
// enumValues[]
|
|
int size = (int)ot->enumValues.GetLength();
|
|
WRITE_NUM(size);
|
|
|
|
for( int n = 0; n < size; n++ )
|
|
{
|
|
WriteString(&ot->enumValues[n]->name);
|
|
WRITE_NUM(ot->enumValues[n]->value);
|
|
}
|
|
}
|
|
else if( ot->flags & asOBJ_TYPEDEF )
|
|
{
|
|
eTokenType t = ot->templateSubType.GetTokenType();
|
|
WRITE_NUM(t);
|
|
}
|
|
else
|
|
{
|
|
WriteObjectType(ot->derivedFrom);
|
|
|
|
// interfaces[]
|
|
int size = (asUINT)ot->interfaces.GetLength();
|
|
WRITE_NUM(size);
|
|
asUINT n;
|
|
for( n = 0; n < ot->interfaces.GetLength(); n++ )
|
|
{
|
|
WriteObjectType(ot->interfaces[n]);
|
|
}
|
|
|
|
// properties[]
|
|
size = (asUINT)ot->properties.GetLength();
|
|
WRITE_NUM(size);
|
|
for( n = 0; n < ot->properties.GetLength(); n++ )
|
|
{
|
|
WriteObjectProperty(ot->properties[n]);
|
|
}
|
|
|
|
// behaviours
|
|
if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
|
|
{
|
|
WriteFunction(engine->scriptFunctions[ot->beh.construct]);
|
|
WriteFunction(engine->scriptFunctions[ot->beh.destruct]);
|
|
WriteFunction(engine->scriptFunctions[ot->beh.factory]);
|
|
size = (int)ot->beh.constructors.GetLength() - 1;
|
|
WRITE_NUM(size);
|
|
for( n = 1; n < ot->beh.constructors.GetLength(); n++ )
|
|
{
|
|
WriteFunction(engine->scriptFunctions[ot->beh.constructors[n]]);
|
|
WriteFunction(engine->scriptFunctions[ot->beh.factories[n]]);
|
|
}
|
|
}
|
|
|
|
// methods[]
|
|
size = (int)ot->methods.GetLength();
|
|
WRITE_NUM(size);
|
|
for( n = 0; n < ot->methods.GetLength(); n++ )
|
|
{
|
|
WriteFunction(engine->scriptFunctions[ot->methods[n]]);
|
|
}
|
|
|
|
// virtualFunctionTable[]
|
|
size = (int)ot->virtualFunctionTable.GetLength();
|
|
WRITE_NUM(size);
|
|
for( n = 0; n < (asUINT)size; n++ )
|
|
{
|
|
WriteFunction(ot->virtualFunctionTable[n]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, bool readProperties)
|
|
{
|
|
if( !readProperties )
|
|
{
|
|
// name
|
|
ReadString(&ot->name);
|
|
// size
|
|
int size;
|
|
READ_NUM(size);
|
|
ot->size = size;
|
|
// flags
|
|
asDWORD flags;
|
|
READ_NUM(flags);
|
|
ot->flags = flags;
|
|
|
|
// Use the default script class behaviours
|
|
ot->beh = engine->scriptTypeBehaviours.beh;
|
|
engine->scriptFunctions[ot->beh.addref]->AddRef();
|
|
engine->scriptFunctions[ot->beh.release]->AddRef();
|
|
engine->scriptFunctions[ot->beh.gcEnumReferences]->AddRef();
|
|
engine->scriptFunctions[ot->beh.gcGetFlag]->AddRef();
|
|
engine->scriptFunctions[ot->beh.gcGetRefCount]->AddRef();
|
|
engine->scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRef();
|
|
engine->scriptFunctions[ot->beh.gcSetFlag]->AddRef();
|
|
engine->scriptFunctions[ot->beh.copy]->AddRef();
|
|
engine->scriptFunctions[ot->beh.factory]->AddRef();
|
|
engine->scriptFunctions[ot->beh.construct]->AddRef();
|
|
for( asUINT i = 1; i < ot->beh.operators.GetLength(); i += 2 )
|
|
engine->scriptFunctions[ot->beh.operators[i]]->AddRef();
|
|
}
|
|
else
|
|
{
|
|
if( ot->flags & asOBJ_ENUM )
|
|
{
|
|
int count;
|
|
READ_NUM(count);
|
|
ot->enumValues.Allocate(count, 0);
|
|
for( int n = 0; n < count; n++ )
|
|
{
|
|
asSEnumValue *e = asNEW(asSEnumValue);
|
|
ReadString(&e->name);
|
|
READ_NUM(e->value);
|
|
ot->enumValues.PushLast(e);
|
|
}
|
|
}
|
|
else if( ot->flags & asOBJ_TYPEDEF )
|
|
{
|
|
eTokenType t;
|
|
READ_NUM(t);
|
|
ot->templateSubType = asCDataType::CreatePrimitive(t, false);
|
|
}
|
|
else
|
|
{
|
|
ot->derivedFrom = ReadObjectType();
|
|
if( ot->derivedFrom )
|
|
ot->derivedFrom->AddRef();
|
|
|
|
// interfaces[]
|
|
int size;
|
|
READ_NUM(size);
|
|
ot->interfaces.Allocate(size,0);
|
|
int n;
|
|
for( n = 0; n < size; n++ )
|
|
{
|
|
asCObjectType *intf = ReadObjectType();
|
|
ot->interfaces.PushLast(intf);
|
|
}
|
|
|
|
// properties[]
|
|
READ_NUM(size);
|
|
ot->properties.Allocate(size,0);
|
|
for( n = 0; n < size; n++ )
|
|
{
|
|
asCObjectProperty *prop = asNEW(asCObjectProperty);
|
|
ReadObjectProperty(prop);
|
|
ot->properties.PushLast(prop);
|
|
}
|
|
|
|
// behaviours
|
|
if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
|
|
{
|
|
asCScriptFunction *func = ReadFunction();
|
|
engine->scriptFunctions[ot->beh.construct]->Release();
|
|
ot->beh.construct = func->id;
|
|
ot->beh.constructors[0] = func->id;
|
|
func->AddRef();
|
|
|
|
func = ReadFunction();
|
|
if( func )
|
|
{
|
|
ot->beh.destruct = func->id;
|
|
func->AddRef();
|
|
}
|
|
|
|
func = ReadFunction();
|
|
engine->scriptFunctions[ot->beh.factory]->Release();
|
|
ot->beh.factory = func->id;
|
|
ot->beh.factories[0] = func->id;
|
|
func->AddRef();
|
|
|
|
READ_NUM(size);
|
|
for( n = 0; n < size; n++ )
|
|
{
|
|
asCScriptFunction *func = ReadFunction();
|
|
ot->beh.constructors.PushLast(func->id);
|
|
func->AddRef();
|
|
|
|
func = ReadFunction();
|
|
ot->beh.factories.PushLast(func->id);
|
|
func->AddRef();
|
|
}
|
|
}
|
|
|
|
// methods[]
|
|
READ_NUM(size);
|
|
for( n = 0; n < size; n++ )
|
|
{
|
|
asCScriptFunction *func = ReadFunction();
|
|
ot->methods.PushLast(func->id);
|
|
func->AddRef();
|
|
}
|
|
|
|
// virtualFunctionTable[]
|
|
READ_NUM(size);
|
|
for( n = 0; n < size; n++ )
|
|
{
|
|
asCScriptFunction *func = ReadFunction();
|
|
ot->virtualFunctionTable.PushLast(func);
|
|
func->AddRef();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void asCRestore::WriteString(asCString* str)
|
|
{
|
|
asUINT len = (asUINT)str->GetLength();
|
|
WRITE_NUM(len);
|
|
stream->Write(str->AddressOf(), (asUINT)len);
|
|
}
|
|
|
|
void asCRestore::ReadString(asCString* str)
|
|
{
|
|
asUINT len;
|
|
READ_NUM(len);
|
|
str->SetLength(len);
|
|
stream->Read(str->AddressOf(), len);
|
|
}
|
|
|
|
void asCRestore::WriteGlobalProperty(asCGlobalProperty* prop)
|
|
{
|
|
// TODO: We might be able to avoid storing the name and type of the global
|
|
// properties twice if we merge this with the WriteUsedGlobalProperties.
|
|
WriteString(&prop->name);
|
|
WriteDataType(&prop->type);
|
|
|
|
// Store the initialization function
|
|
if( prop->initFunc )
|
|
{
|
|
bool f = true;
|
|
WRITE_NUM(f);
|
|
|
|
WriteFunction(prop->initFunc);
|
|
}
|
|
else
|
|
{
|
|
bool f = false;
|
|
WRITE_NUM(f);
|
|
}
|
|
}
|
|
|
|
void asCRestore::ReadGlobalProperty()
|
|
{
|
|
asCString name;
|
|
asCDataType type;
|
|
|
|
ReadString(&name);
|
|
ReadDataType(&type);
|
|
|
|
asCGlobalProperty *prop = module->AllocateGlobalProperty(name.AddressOf(), type);
|
|
|
|
// Read the initialization function
|
|
bool f;
|
|
READ_NUM(f);
|
|
if( f )
|
|
{
|
|
asCScriptFunction *func = ReadFunction(false, true);
|
|
|
|
// refCount was already set to 1
|
|
prop->initFunc = func;
|
|
}
|
|
}
|
|
|
|
void asCRestore::WriteObjectProperty(asCObjectProperty* prop)
|
|
{
|
|
WriteString(&prop->name);
|
|
WriteDataType(&prop->type);
|
|
WRITE_NUM(prop->byteOffset);
|
|
}
|
|
|
|
void asCRestore::ReadObjectProperty(asCObjectProperty* prop)
|
|
{
|
|
ReadString(&prop->name);
|
|
ReadDataType(&prop->type);
|
|
READ_NUM(prop->byteOffset);
|
|
}
|
|
|
|
void asCRestore::WriteDataType(const asCDataType *dt)
|
|
{
|
|
bool b;
|
|
int t = dt->GetTokenType();
|
|
WRITE_NUM(t);
|
|
WriteObjectType(dt->GetObjectType());
|
|
b = dt->IsObjectHandle();
|
|
WRITE_NUM(b);
|
|
b = dt->IsReadOnly();
|
|
WRITE_NUM(b);
|
|
b = dt->IsHandleToConst();
|
|
WRITE_NUM(b);
|
|
b = dt->IsReference();
|
|
WRITE_NUM(b);
|
|
}
|
|
|
|
void asCRestore::ReadDataType(asCDataType *dt)
|
|
{
|
|
eTokenType tokenType;
|
|
READ_NUM(tokenType);
|
|
asCObjectType *objType = ReadObjectType();
|
|
bool isObjectHandle;
|
|
READ_NUM(isObjectHandle);
|
|
bool isReadOnly;
|
|
READ_NUM(isReadOnly);
|
|
bool isHandleToConst;
|
|
READ_NUM(isHandleToConst);
|
|
bool isReference;
|
|
READ_NUM(isReference);
|
|
|
|
if( tokenType == ttIdentifier )
|
|
*dt = asCDataType::CreateObject(objType, false);
|
|
else
|
|
*dt = asCDataType::CreatePrimitive(tokenType, false);
|
|
if( isObjectHandle )
|
|
{
|
|
dt->MakeReadOnly(isHandleToConst);
|
|
dt->MakeHandle(true);
|
|
}
|
|
dt->MakeReadOnly(isReadOnly);
|
|
dt->MakeReference(isReference);
|
|
}
|
|
|
|
void asCRestore::WriteObjectType(asCObjectType* ot)
|
|
{
|
|
char ch;
|
|
|
|
// Only write the object type name
|
|
if( ot )
|
|
{
|
|
// Check for template instances/specializations
|
|
if( ot->templateSubType.GetTokenType() != ttUnrecognizedToken &&
|
|
ot != engine->defaultArrayObjectType )
|
|
{
|
|
ch = 'a';
|
|
WRITE_NUM(ch);
|
|
|
|
if( ot->templateSubType.IsObject() )
|
|
{
|
|
ch = 's';
|
|
WRITE_NUM(ch);
|
|
WriteObjectType(ot->templateSubType.GetObjectType());
|
|
|
|
if( ot->templateSubType.IsObjectHandle() )
|
|
ch = 'h';
|
|
else
|
|
ch = 'o';
|
|
WRITE_NUM(ch);
|
|
}
|
|
else
|
|
{
|
|
ch = 't';
|
|
WRITE_NUM(ch);
|
|
eTokenType t = ot->templateSubType.GetTokenType();
|
|
WRITE_NUM(t);
|
|
}
|
|
}
|
|
else if( ot->flags & asOBJ_TEMPLATE_SUBTYPE )
|
|
{
|
|
ch = 's';
|
|
WRITE_NUM(ch);
|
|
WriteString(&ot->name);
|
|
}
|
|
else
|
|
{
|
|
ch = 'o';
|
|
WRITE_NUM(ch);
|
|
WriteString(&ot->name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ch = '\0';
|
|
WRITE_NUM(ch);
|
|
// Write a null string
|
|
asDWORD null = 0;
|
|
WRITE_NUM(null);
|
|
}
|
|
}
|
|
|
|
asCObjectType* asCRestore::ReadObjectType()
|
|
{
|
|
asCObjectType *ot;
|
|
char ch;
|
|
READ_NUM(ch);
|
|
if( ch == 'a' )
|
|
{
|
|
READ_NUM(ch);
|
|
if( ch == 's' )
|
|
{
|
|
ot = ReadObjectType();
|
|
asCDataType dt = asCDataType::CreateObject(ot, false);
|
|
|
|
READ_NUM(ch);
|
|
if( ch == 'h' )
|
|
dt.MakeHandle(true);
|
|
|
|
dt.MakeArray(engine);
|
|
ot = dt.GetObjectType();
|
|
|
|
asASSERT(ot);
|
|
}
|
|
else
|
|
{
|
|
eTokenType tokenType;
|
|
READ_NUM(tokenType);
|
|
asCDataType dt = asCDataType::CreatePrimitive(tokenType, false);
|
|
dt.MakeArray(engine);
|
|
ot = dt.GetObjectType();
|
|
|
|
asASSERT(ot);
|
|
}
|
|
}
|
|
else if( ch == 's' )
|
|
{
|
|
// Read the name of the template subtype
|
|
asCString typeName;
|
|
ReadString(&typeName);
|
|
|
|
// Find the template subtype
|
|
for( asUINT n = 0; n < engine->templateSubTypes.GetLength(); n++ )
|
|
{
|
|
if( engine->templateSubTypes[n] && engine->templateSubTypes[n]->name == typeName )
|
|
{
|
|
ot = engine->templateSubTypes[n];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// TODO: Should give a friendly error in case the template type isn't found
|
|
asASSERT(ot);
|
|
}
|
|
else
|
|
{
|
|
// Read the object type name
|
|
asCString typeName;
|
|
ReadString(&typeName);
|
|
|
|
if( typeName.GetLength() && typeName != "_builtin_object_" )
|
|
{
|
|
// Find the object type
|
|
ot = module->GetObjectType(typeName.AddressOf());
|
|
if( !ot )
|
|
ot = engine->GetObjectType(typeName.AddressOf());
|
|
|
|
asASSERT(ot);
|
|
}
|
|
else if( typeName == "_builtin_object_" )
|
|
{
|
|
ot = &engine->scriptTypeBehaviours;
|
|
}
|
|
else
|
|
ot = 0;
|
|
}
|
|
|
|
return ot;
|
|
}
|
|
|
|
void asCRestore::WriteByteCode(asDWORD *bc, int length)
|
|
{
|
|
while( length )
|
|
{
|
|
asDWORD c = *(asBYTE*)bc;
|
|
|
|
if( c == asBC_ALLOC )
|
|
{
|
|
WRITE_NUM(*bc++);
|
|
asDWORD tmp[MAX_DATA_SIZE];
|
|
int n;
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
tmp[n] = *bc++;
|
|
|
|
// Translate the object type
|
|
asCObjectType *ot = *(asCObjectType**)tmp;
|
|
*(int*)tmp = FindObjectTypeIdx(ot);
|
|
|
|
// Translate the constructor func id, if it is a script class
|
|
if( ot->flags & asOBJ_SCRIPT_OBJECT )
|
|
*(int*)&tmp[AS_PTR_SIZE] = FindFunctionIndex(engine->scriptFunctions[*(int*)&tmp[AS_PTR_SIZE]]);
|
|
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
WRITE_NUM(tmp[n]);
|
|
}
|
|
else if( c == asBC_FREE ||
|
|
c == asBC_REFCPY ||
|
|
c == asBC_OBJTYPE )
|
|
{
|
|
WRITE_NUM(*bc++);
|
|
// Translate object type pointers into indices
|
|
asDWORD tmp[MAX_DATA_SIZE];
|
|
int n;
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
tmp[n] = *bc++;
|
|
|
|
*(int*)tmp = FindObjectTypeIdx(*(asCObjectType**)tmp);
|
|
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
WRITE_NUM(tmp[n]);
|
|
}
|
|
else if( c == asBC_TYPEID )
|
|
{
|
|
WRITE_NUM(*bc++);
|
|
|
|
// Translate type ids into indices
|
|
asDWORD tmp[MAX_DATA_SIZE];
|
|
int n;
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
tmp[n] = *bc++;
|
|
|
|
*(int*)tmp = FindTypeIdIdx(*(int*)tmp);
|
|
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
WRITE_NUM(tmp[n]);
|
|
}
|
|
else if( c == asBC_CALL ||
|
|
c == asBC_CALLINTF ||
|
|
c == asBC_CALLSYS )
|
|
{
|
|
WRITE_NUM(*bc++);
|
|
|
|
// Translate the function id
|
|
asDWORD tmp[MAX_DATA_SIZE];
|
|
int n;
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
tmp[n] = *bc++;
|
|
|
|
*(int*)tmp = FindFunctionIndex(engine->scriptFunctions[*(int*)tmp]);
|
|
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
WRITE_NUM(tmp[n]);
|
|
}
|
|
else if( c == asBC_STR )
|
|
{
|
|
asDWORD tmp = *bc++;
|
|
|
|
// Translate the string constant id
|
|
asWORD *arg = ((asWORD*)&tmp)+1;
|
|
*arg = FindStringConstantIndex(*arg);
|
|
WRITE_NUM(tmp);
|
|
}
|
|
else if( c == asBC_CALLBND )
|
|
{
|
|
WRITE_NUM(*bc++);
|
|
|
|
// Translate the function id
|
|
int funcId = *bc++;
|
|
for( asUINT n = 0; n < module->bindInformations.GetLength(); n++ )
|
|
if( module->bindInformations[n]->importedFunctionSignature->id == funcId )
|
|
{
|
|
funcId = n;
|
|
break;
|
|
}
|
|
|
|
WRITE_NUM(funcId);
|
|
}
|
|
else if( c == asBC_PGA ||
|
|
c == asBC_LDG ||
|
|
c == asBC_PshG4 ||
|
|
c == asBC_LdGRdR4 ||
|
|
c == asBC_CpyGtoV4 ||
|
|
c == asBC_CpyVtoG4 ||
|
|
c == asBC_SetG4 )
|
|
{
|
|
WRITE_NUM(*bc++);
|
|
|
|
// Translate global variable pointers into indices
|
|
asDWORD tmp[MAX_DATA_SIZE];
|
|
int n;
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
tmp[n] = *bc++;
|
|
|
|
*(int*)tmp = FindGlobalPropPtrIndex(*(void**)tmp);
|
|
|
|
for( n = 0; n < asBCTypeSize[asBCInfo[c].type]-1; n++ )
|
|
WRITE_NUM(tmp[n]);
|
|
}
|
|
else
|
|
{
|
|
// Store the bc as is
|
|
for( int n = 0; n < asBCTypeSize[asBCInfo[c].type]; n++ )
|
|
WRITE_NUM(*bc++);
|
|
}
|
|
|
|
length -= asBCTypeSize[asBCInfo[c].type];
|
|
}
|
|
}
|
|
|
|
void asCRestore::ReadByteCode(asDWORD *bc, int length)
|
|
{
|
|
while( length )
|
|
{
|
|
asDWORD c;
|
|
READ_NUM(c);
|
|
*bc = c;
|
|
bc += 1;
|
|
c = *(asBYTE*)&c;
|
|
|
|
// Read the bc as is
|
|
for( int n = 1; n < asBCTypeSize[asBCInfo[c].type]; n++ )
|
|
READ_NUM(*bc++);
|
|
|
|
length -= asBCTypeSize[asBCInfo[c].type];
|
|
}
|
|
}
|
|
|
|
void asCRestore::WriteUsedTypeIds()
|
|
{
|
|
asUINT count = (asUINT)usedTypeIds.GetLength();
|
|
WRITE_NUM(count);
|
|
for( asUINT n = 0; n < count; n++ )
|
|
WriteDataType(engine->GetDataTypeFromTypeId(usedTypeIds[n]));
|
|
}
|
|
|
|
void asCRestore::ReadUsedTypeIds()
|
|
{
|
|
asUINT n;
|
|
asUINT count;
|
|
READ_NUM(count);
|
|
usedTypeIds.SetLength(count);
|
|
for( n = 0; n < count; n++ )
|
|
{
|
|
asCDataType dt;
|
|
ReadDataType(&dt);
|
|
usedTypeIds[n] = engine->GetTypeIdFromDataType(dt);
|
|
}
|
|
}
|
|
|
|
int asCRestore::FindGlobalPropPtrIndex(void *ptr)
|
|
{
|
|
int i = usedGlobalProperties.IndexOf(ptr);
|
|
if( i >= 0 ) return i;
|
|
|
|
usedGlobalProperties.PushLast(ptr);
|
|
return (int)usedGlobalProperties.GetLength()-1;
|
|
}
|
|
|
|
void asCRestore::WriteUsedGlobalProps()
|
|
{
|
|
int c = (int)usedGlobalProperties.GetLength();
|
|
WRITE_NUM(c);
|
|
|
|
for( int n = 0; n < c; n++ )
|
|
{
|
|
size_t *p = (size_t*)usedGlobalProperties[n];
|
|
|
|
// First search for the global in the module
|
|
char moduleProp = 0;
|
|
asCGlobalProperty *prop = 0;
|
|
for( int i = 0; i < (signed)module->scriptGlobals.GetLength(); i++ )
|
|
{
|
|
if( p == module->scriptGlobals[i]->GetAddressOfValue() )
|
|
{
|
|
prop = module->scriptGlobals[i];
|
|
moduleProp = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If it is not in the module, it must be an application registered property
|
|
if( !prop )
|
|
{
|
|
for( int i = 0; i < (signed)engine->registeredGlobalProps.GetLength(); i++ )
|
|
{
|
|
if( engine->registeredGlobalProps[i]->GetAddressOfValue() == p )
|
|
{
|
|
prop = engine->registeredGlobalProps[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
asASSERT(prop);
|
|
|
|
// Store the name and type of the property so we can find it again on loading
|
|
WriteString(&prop->name);
|
|
WriteDataType(&prop->type);
|
|
|
|
// Also store whether the property is a module property or a registered property
|
|
WRITE_NUM(moduleProp);
|
|
}
|
|
}
|
|
|
|
void asCRestore::ReadUsedGlobalProps()
|
|
{
|
|
int c;
|
|
READ_NUM(c);
|
|
|
|
usedGlobalProperties.SetLength(c);
|
|
|
|
for( int n = 0; n < c; n++ )
|
|
{
|
|
asCString name;
|
|
asCDataType type;
|
|
char moduleProp;
|
|
|
|
ReadString(&name);
|
|
ReadDataType(&type);
|
|
READ_NUM(moduleProp);
|
|
|
|
// Find the real property
|
|
void *prop = 0;
|
|
if( moduleProp )
|
|
{
|
|
for( asUINT p = 0; p < module->scriptGlobals.GetLength(); p++ )
|
|
{
|
|
if( module->scriptGlobals[p]->name == name &&
|
|
module->scriptGlobals[p]->type == type )
|
|
{
|
|
prop = module->scriptGlobals[p]->GetAddressOfValue();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( asUINT p = 0; p < engine->registeredGlobalProps.GetLength(); p++ )
|
|
{
|
|
if( engine->registeredGlobalProps[p] &&
|
|
engine->registeredGlobalProps[p]->name == name &&
|
|
engine->registeredGlobalProps[p]->type == type )
|
|
{
|
|
prop = engine->registeredGlobalProps[p]->GetAddressOfValue();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: If the property isn't found, we must give an error
|
|
asASSERT(prop);
|
|
|
|
usedGlobalProperties[n] = prop;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------
|
|
// Miscellaneous
|
|
//---------------------------------------------------------------------------------------------------
|
|
|
|
int asCRestore::FindFunctionIndex(asCScriptFunction *func)
|
|
{
|
|
asUINT n;
|
|
for( n = 0; n < usedFunctions.GetLength(); n++ )
|
|
{
|
|
if( usedFunctions[n] == func )
|
|
return n;
|
|
}
|
|
|
|
usedFunctions.PushLast(func);
|
|
return (int)usedFunctions.GetLength() - 1;
|
|
}
|
|
|
|
asCScriptFunction *asCRestore::FindFunction(int idx)
|
|
{
|
|
return usedFunctions[idx];
|
|
}
|
|
|
|
void asCRestore::TranslateFunction(asCScriptFunction *func)
|
|
{
|
|
asUINT n;
|
|
asDWORD *bc = func->byteCode.AddressOf();
|
|
for( n = 0; n < func->byteCode.GetLength(); )
|
|
{
|
|
int c = *(asBYTE*)&bc[n];
|
|
if( c == asBC_FREE ||
|
|
c == asBC_REFCPY || c == asBC_OBJTYPE )
|
|
{
|
|
// Translate the index to the true object type
|
|
asPTRWORD *ot = (asPTRWORD*)&bc[n+1];
|
|
*(asCObjectType**)ot = FindObjectType(*(int*)ot);
|
|
}
|
|
else if( c == asBC_TYPEID )
|
|
{
|
|
// Translate the index to the type id
|
|
int *tid = (int*)&bc[n+1];
|
|
*tid = FindTypeId(*tid);
|
|
}
|
|
else if( c == asBC_CALL ||
|
|
c == asBC_CALLINTF ||
|
|
c == asBC_CALLSYS )
|
|
{
|
|
// Translate the index to the func id
|
|
int *fid = (int*)&bc[n+1];
|
|
*fid = FindFunction(*fid)->id;
|
|
}
|
|
else if( c == asBC_ALLOC )
|
|
{
|
|
// Translate the index to the true object type
|
|
asPTRWORD *arg = (asPTRWORD*)&bc[n+1];
|
|
*(asCObjectType**)arg = FindObjectType(*(int*)arg);
|
|
|
|
// If the object type is a script class then the constructor id must be translated
|
|
asCObjectType *ot = *(asCObjectType**)arg;
|
|
if( ot->flags & asOBJ_SCRIPT_OBJECT )
|
|
{
|
|
int *fid = (int*)&bc[n+1+AS_PTR_SIZE];
|
|
*fid = FindFunction(*fid)->id;
|
|
}
|
|
}
|
|
else if( c == asBC_STR )
|
|
{
|
|
// Translate the index to the true string id
|
|
asWORD *arg = ((asWORD*)&bc[n])+1;
|
|
|
|
*arg = usedStringConstants[*arg];
|
|
}
|
|
else if( c == asBC_CALLBND )
|
|
{
|
|
// Translate the function id
|
|
int *fid = (int*)&bc[n+1];
|
|
*fid = module->bindInformations[*fid]->importedFunctionSignature->id;
|
|
}
|
|
else if( c == asBC_PGA ||
|
|
c == asBC_LDG ||
|
|
c == asBC_PshG4 ||
|
|
c == asBC_LdGRdR4 ||
|
|
c == asBC_CpyGtoV4 ||
|
|
c == asBC_CpyVtoG4 ||
|
|
c == asBC_SetG4 )
|
|
{
|
|
// Translate the global var index to pointer
|
|
asPTRWORD *index = (asPTRWORD*)&bc[n+1];
|
|
*(void**)index = usedGlobalProperties[*(int*)index];
|
|
}
|
|
|
|
n += asBCTypeSize[asBCInfo[c].type];
|
|
}
|
|
}
|
|
|
|
int asCRestore::FindTypeIdIdx(int typeId)
|
|
{
|
|
asUINT n;
|
|
for( n = 0; n < usedTypeIds.GetLength(); n++ )
|
|
{
|
|
if( usedTypeIds[n] == typeId )
|
|
return n;
|
|
}
|
|
|
|
usedTypeIds.PushLast(typeId);
|
|
return (int)usedTypeIds.GetLength() - 1;
|
|
}
|
|
|
|
int asCRestore::FindTypeId(int idx)
|
|
{
|
|
return usedTypeIds[idx];
|
|
}
|
|
|
|
int asCRestore::FindObjectTypeIdx(asCObjectType *obj)
|
|
{
|
|
asUINT n;
|
|
for( n = 0; n < usedTypes.GetLength(); n++ )
|
|
{
|
|
if( usedTypes[n] == obj )
|
|
return n;
|
|
}
|
|
|
|
usedTypes.PushLast(obj);
|
|
return (int)usedTypes.GetLength() - 1;
|
|
}
|
|
|
|
asCObjectType *asCRestore::FindObjectType(int idx)
|
|
{
|
|
return usedTypes[idx];
|
|
}
|
|
|
|
END_AS_NAMESPACE
|
|
|