+ const FieldDescription &fd(td.GetField(i->first));
+ const TypeDescription &fieldType(TypeDescription::Get(fd.TypeId()));
+ if (CanLink(*i->second)) {
+ char *dest(object + fd.Offset());
+ if (fd.IsAggregate()) {
+ int arraySize(i->second->GetLiteral().ArraySize());
+ char *aggregate(alloc.Alloc(fieldType.Size() * arraySize));
+ char *iter(aggregate);
+ if (i->second->GetLiteral().GetType() == Literal::ARRAY_PROPS) {
+ const vector<PropertyList *> &list(i->second->GetLiteral().GetPropertyLists());
+ for (vector<PropertyList *>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) {
+ fieldType.Construct(iter);
+ ReadObject(fieldType.TypeId(), -1, iter, **j);
+ }
+ } else {
+ const vector<Value *> &list(i->second->GetLiteral().GetValues());
+ for (vector<Value *>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) {
+ fieldType.Construct(iter);
+ ReadLiteral(fieldType.TypeId(), -1, iter, (*j)->GetLiteral());
+ }
+ }
+ if (fd.IsReferenced()) {
+ std::memcpy(dest, &aggregate, sizeof(char *));
+ dest += sizeof(char *);
+ std::memcpy(dest, &arraySize, sizeof(int));
+ } else {
+ throw Error("aggregate type fields must be referenced");
+ }
+ } else if (i->second->IsLiteral() && !fd.IsReferenced()) {
+ // inline literals
+ if (i->second->GetLiteral().IsObject()) {
+ ReadObject(fd.TypeId(), -1, dest, *i->second->GetLiteral().GetProperties());
+ } else {
+ ReadLiteral(fd.TypeId(), -1, dest, i->second->GetLiteral());
+ }
+ } else {
+ char *src(reinterpret_cast<char *>(GetObject(fd.TypeId(), *i->second)));
+ if (fd.TypeId() == TypeDescription::GetTypeId("Image")) {
+ src = reinterpret_cast<char *>(GetImage(src));
+ }
+ if (fd.IsReferenced()) {
+ std::memcpy(dest, &src, sizeof(char *));
+ } else {
+ std::memcpy(dest, src, fieldType.Size());
+ }
+ }
+ } else {
+ Postpone(typeId, id, fd.Offset(), i->second->GetIdentifier(), fd.TypeId(), !fd.IsReferenced());
+ }
+ }
+ td.Load(object);
+}
+
+
+void Interpreter::ReadScript(const std::vector<ScriptToken *> &s, Script *script) {
+ int size(0);
+ for (vector<ScriptToken *>::const_iterator i(s.begin()), end(s.end()); i != end; ++i) {
+ if ((*i)->GetType() != ScriptToken::COMMAND) {
+ throw Error("unexpected script token");
+ }
+ ++size;
+ const string &cmd((*i)->CommandName());
+ if (cmd == "move") {
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after move");
+ }
+ const string ®((*i)->RegisterName());
+ switch (reg[0]) {
+ case 'a':
+ size += sizeof(void *);
+ break;
+ case 'i':
+ size += sizeof(int);
+ break;
+ case 'v':
+ size += sizeof(Vector<int>);
+ break;
+ default:
+ throw Error("unknown register " + reg);
+ }
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after move");
+ }
+ } else if (cmd == "add") {
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after add");
+ }
+ const string ®((*i)->RegisterName());
+ switch (reg[0]) {
+ case 'i':
+ size += sizeof(int);
+ break;
+ case 'v':
+ size += sizeof(Vector<int>);
+ break;
+ default:
+ throw Error("expected register after add " + reg);
+ }
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after add");
+ }
+ } else if (cmd == "mod") {
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after mod");
+ }
+ size += sizeof(int);
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after mod");
+ }
+ } else if (cmd == "rand") {
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after rand");
+ }
+ size += sizeof(int);
+ ++i;
+ if (i == end) {
+ throw Error("unexpected script end after rand");
+ }
+ } else if (cmd == "sysc") {
+
+ } else {
+ throw Error("unknown command " + cmd);
+ }
+ }
+
+ unsigned char *text(reinterpret_cast<unsigned char *>(alloc.Alloc(size)));
+ int cursor(0);
+ for (vector<ScriptToken *>::const_iterator i(s.begin()), end(s.end()); i != end; ++i) {
+ if ((*i)->GetType() != ScriptToken::COMMAND) {
+ throw Error("unexpected script token");
+ }
+ const string &cmd((*i)->CommandName());
+ if (cmd == "move") {
+ ++i;
+ const string ®((*i)->RegisterName());
+ ++i;
+ if (reg == "a0") {
+ text[cursor] = Script::CODE_MOVE_A0;
+ ++cursor;
+ ReadScriptAddress(**i, text + cursor);
+ cursor += sizeof(void *);
+ } else if (reg == "a1") {
+ text[cursor] = Script::CODE_MOVE_A1;
+ ++cursor;
+ ReadScriptAddress(**i, text + cursor);
+ cursor += sizeof(void *);
+ } else if (reg == "i0") {
+ text[cursor] = Script::CODE_MOVE_I0;
+ ++cursor;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ } else if (reg == "i1") {
+ text[cursor] = Script::CODE_MOVE_I1;
+ ++cursor;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ } else if (reg == "v0") {
+ text[cursor] = Script::CODE_MOVE_V0;
+ ++cursor;
+ ReadScriptVector(**i, text + cursor);
+ cursor += sizeof(Vector<int>);
+ } else if (reg == "v1") {
+ text[cursor] = Script::CODE_MOVE_V1;
+ ++cursor;
+ ReadScriptVector(**i, text + cursor);
+ cursor += sizeof(Vector<int>);
+ } else {
+ throw Error("unknown register " + reg);
+ }
+ } else if (cmd == "add") {
+ ++i;
+ const string ®((*i)->RegisterName());
+ ++i;
+ if (reg == "i0") {
+ text[cursor] = Script::CODE_ADD_I0;
+ ++cursor;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ } else if (reg == "i1") {
+ text[cursor] = Script::CODE_ADD_I1;
+ ++cursor;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ } else if (reg == "v0") {
+ text[cursor] = Script::CODE_ADD_V0;
+ ++cursor;
+ ReadScriptVector(**i, text + cursor);
+ cursor += sizeof(Vector<int>);
+ } else if (reg == "v1") {
+ text[cursor] = Script::CODE_ADD_V1;
+ ++cursor;
+ ReadScriptVector(**i, text + cursor);
+ cursor += sizeof(Vector<int>);
+ } else {
+ throw Error("unexpected register " + reg);
+ }
+ } else if (cmd == "mod") {
+ ++i;
+ const string ®((*i)->RegisterName());
+ ++i;
+ if (reg == "i0") {
+ text[cursor] = Script::CODE_MOD_I0;
+ ++cursor;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ } else if (reg == "i1") {
+ text[cursor] = Script::CODE_MOD_I1;
+ ++cursor;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ } else {
+ throw Error("unexpected register " + reg);
+ }
+ } else if (cmd == "rand") {
+ ++i;
+ const string ®((*i)->RegisterName());
+ if (reg == "i0") {
+ text[cursor] = Script::CODE_RAND_I0;
+ ++cursor;
+ } else if (reg == "i1") {
+ text[cursor] = Script::CODE_RAND_I1;
+ ++cursor;