Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define NOT_A_SCRATCH_1_FILE 0
- #define BAD_FILE_VERSION 1
- #define INFO_MAP_EXPECTED 2
- #define STAGE_EXPECTED 3
- #define Vector std::vector
- #define ObjectTable scratch1::object_table
- #define Object scratch1::object
- #define Project scratch1::project
- #define InputStream std::istream
- #define String std::string
- #define ObjectReference scratch1::object_reference
- #define ConstantObject scratch1::object_constant
- #define ArrayObject scratch1::object_array
- #define MapObject scratch1::object_map
- #define LongInt sb1::long_int
- #define SoundData sb1::sound
- #define BitmapData sb1::bitmap_data
- #define Color scratch1::color
- #define Point sb1::point
- #define Rect sb1::rect
- #define Form sb1::form
- #define ColorForm sb1::form_color
- Project read (InputStream input) {
- if (readString(input, 8).compare("ScratchV")) throw NOT_A_SCRATCH_1_FILE;
- String s = readString(input, 2);
- if (s.compare("01") | s.compare("02")) throw BAD_FILE_VERSION;
- readString(input, 4);
- ObjectTable info = readObjectTable(input);
- ObjectTable content = readObjectTable(input);
- return build(info, content);
- }
- Project read (ObjectTable info, ObjectTable content) {
- Project project = Project();
- if (info[0].getType() != 24) throw INFO_MAP_EXPECTED;
- MapObject dict = reinterpret_cast<MapObject>(info[0]);
- project.setThumbnail(readForm(dict.getAs("thumbnail", 34)));
- project.setAuthor(dict.getAs("author", 9, 10, 14));
- project.setVersion(dict.getAs("version", 9, 10, 14));
- project.setProperty("language", dict["language"]);
- project.setProperty("platform", dict["platform"]);
- project.setProperty("history", dict["history"]);
- project.setProperty("comment", dict["comment"]);
- project.setProperty("os-version", dict["os-version"]);
- if (content[0].getType() != 125) throw STAGE_EXPECTED;
- double zoom = 1;
- int xPan = 0, yPan = 0;
- UserClassObject stage = ((UserClassObject) content[0]);
- if (stage[12].isNumeric()) zoom = stage[12].getAsDouble();
- if (stage[13].isNumeric()) xPan = stage[13].getAsInt();
- if (stage[14].isNumeric()) yPan = stage[14].getAsInt();
- Rect inputSpace = (stage[0].isReference() && reinterpret_cast<ObjectReference>(stage[0]).dereference().getType() == 33) ? reinterpret_cast<Rect>(reinterpret_cast<ObjectReference>(stage[6]).dereference().getValue()) : Rect(0, 0, 480, 360);
- Rect outputSpace = Rect(-xPan, yPan, (480 - xPan) * zoom / 100, (360 + yPan) * zoom / 100);
- project.setRenderTransform(inputSpace, outputSpace);
- if (!stage[15].isNull()) printf("obsoleteSavedState property non-null");
- project.setVolume(stage[17].isNumeric() ? stage[17].getAsDouble() : 1);
- project.setTempo(stage[18].isNumeric() ? stage[18].getAsInt() : 60);
- readSprites(stage[16], &project);
- // TODO: sceneStates field, [19]
- readLists(stage[20], &project);
- if (stage.getAsReference(6, 99).dereference().isString() && stage.getAsReference(6, 99).dereference().getAsString().compare("Stage")) throw MALFORMED_STAGE;
- project.setVariables(readVariables(stage[7]));
- Stage s = Stage();
- s.loadBlocks(readBlocks(stage[8]));
- if (stage[9].isBool() && stage[9].getAsBool()) throw MALFORMED_STAGE;
- s.loadMedia(readMedia(stage[10]));
- if (stage[11].isNumeric()) s.costume = stage[11].getAsInt();
- // TODO: color field, [3]; flags, [4]; properties, [5];
- }
- Vector<Asset> readMedia (Object obj1) {
- if (!obj1.isReference() || !reinterpret_cast<ObjectReference>(obj1).dereference().isArray()) throw MALFORMED_MEDIA;
- Vector<Object> v = reinterpret_cast<ObjectReference>(obj1).dereference().getAsArray();
- int i = v.size();
- Vector<Asset> ret = Vector<Asset>(size);
- for (int i = 0; i < size; i++)
- ret[i] = readAsset(v[i]);
- return ret;
- }
- Asset readAsset (Object obj1) {
- if (!obj1.isReference() || !reinterpret_cast<ObjectReference>(obj1).dereference().isUserClass()) throw MALFORMED_ASSET;
- UserClassObject a = reinterpret_cast<ObjectReference>(obj1).dereference().getAsUserClass();
- int type = a.getType();
- switch (type) {
- case 162:
- Asset a = readForm(a.getAs(1, 34));
- String readString (InputStream input, int size) {
- char* s = new char[size];
- input.read(s, size);
- return String(s, size);
- }
- unsigned short readShort (InputStream input) {
- return reinterpret_cast<unsigned short>((input.get() << 8) | input.get());
- }
- unsigned int readInt (InputStream input) {
- return reinterpret_cast<unsigned int>((input.get() << 24) | (input.get() << 16) | (input.get() << 8) | input.get());
- }
- int read24Bit (InputStream input) {
- return (input.get() << 16) | (input.get() << 8) | input.get();
- }
- unsigned long readLong (InputStream input) {
- return (reinterpret_cast<unsigned long>((input.get() << 24) | (input.get() << 16) | (input.get() << 8) | input.get()) << 32) | reinterpret_cast<unsigned long>((input.get() << 24) | (input.get() << 16) | (input.get() << 8) | input.get());
- }
- ObjectTable readObjectTable (InputStream input) {
- if (readString(input, 10).compare("ObjS\0Stch\0")) throw NOT_AN_OBJECT_TABLE;
- unsigned int len = readInt(input);
- ObjectTable table = ObjectTable(len);
- for (unsigned int i = 0; i < len; i++)
- table[i] = readObject(input, false, &table);
- return table;
- }
- Object readObject (InputStream input, ObjectTable* table) {
- Object tryInline = readInline(input, table);
- if (tryInline) return tryInline;
- if (type > 99) return readUserClass(input.seekg(input.tellg() - 1), table);
- int type = input.get();
- switch (type) {
- case 9:
- case 10:
- case 11:
- case 14:
- return ConstantObject<String>(readString(input, readInt(input)));
- case 12:
- unsigned int length = readInt(input) * 2;
- return ConstantObject<SoundData>(SoundData(readString(input).c_str(), length));
- case 13:
- unsigned int length = readInt(input) * 4;
- return ConstantObject<BitmapData>(SoundData(readString(input).c_str(), length));
- case 20:
- case 21:
- case 22:
- case 23:
- unsigned int length = readInt(input);
- ArrayObject array = new ArrayObject(length);
- for (unsigned int i = 0; i < length; i++)
- array[i] = readInline(input, table);
- return array;
- case 24:
- case 25:
- unsigned int length = readInt(input) * 2;
- MapObject array = new MapObject(length);
- for (unsigned int i = 0; i < length; i++)
- array.put(readInline(input, table), readInline(input, table));
- return array;
- case 30:
- case 31:
- unsigned int color = readInt(input);
- short r = (color & 0x3FF00000) >> 20;
- short g = (color & 0x000FFC00) >> 10;
- short b = color & 0x000003FF;
- int a = (type == 31) ? input.get() : 0xFF;
- return ConstantObject<Color>(Color(r, g, b, a));
- case 32:
- return ConstantObject<Point>(Point(readInline(input, table), readInline(input, table)));
- case 33:
- return ConstantObject<Rect>(Rect(readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table)));
- case 34:
- return ConstantObject<Form>(Form(readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table)));
- case 35:
- return ConstantObject<ColorForm>(ColorForm(readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table)));
- default:
- throw UNKNOWN_FIXED_FORMAT_TYPE;
- }
- }
- Object readInline (InputStream input, ObjectTable* table) {
- int type = input.get();
- switch (type) {
- case 1:
- return ConstantObject.NIL;
- case 2:
- return ConstantObject.TRUE;
- case 3:
- return ConstantObject.FALSE;
- case 4:
- return ConstantObject<int>(reinterpret_cast<int>(readInt(input)));
- case 5:
- return ConstantObject<short>(reinterpret_cast<short>(readShort(input)));
- case 6:
- case 7:
- unsigned short bytes = readShort(input);
- return ConstantObject<LongInt>(LongInt(readString(input, bytes).c_str(), bytes, type == 7));
- case 8:
- return ConstantObject<double>(*(reinterpret_cast<double*>(&read_long(input))));
- case 99:
- return ObjectReference(read24Bit(input), table);
- default:
- input.seekg(input.tellg() - 1);
- return NULL;
- }
- }
- Object readUserClass (InputStream input, ObjectTable* table) {
- int type = input.get();
- int version = input.get();
- int fieldLength = input.get();
- Vector<Object> fields = Vector<Object>(fieldLength);
- for (int i = 0; i < fieldsLength; i++)
- fields[i] = readInline(input, table);
- return UserClassObject(type, version, fields);
- }
- namespace scratch1 {
- class object_table {
- Object* objects;
- unsigned int size;
- public:
- object_table (unsigned int size) {
- this->objects = new Object[size];
- this->size = size;
- }
- Object* operator [] (unsigned int access) {
- return this->objects[access];
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment