SforzandoCF

sb

Oct 3rd, 2025 (edited)
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.48 KB | None | 0 0
  1. #define NOT_A_SCRATCH_1_FILE    0
  2. #define BAD_FILE_VERSION        1
  3. #define INFO_MAP_EXPECTED       2
  4. #define STAGE_EXPECTED          3
  5.  
  6. #define Vector          std::vector
  7. #define ObjectTable     scratch1::object_table
  8. #define Object          scratch1::object
  9. #define Project         scratch1::project
  10. #define InputStream     std::istream
  11. #define String          std::string
  12. #define ObjectReference scratch1::object_reference
  13. #define ConstantObject  scratch1::object_constant
  14. #define ArrayObject     scratch1::object_array
  15. #define MapObject       scratch1::object_map
  16. #define LongInt         sb1::long_int
  17. #define SoundData       sb1::sound
  18. #define BitmapData      sb1::bitmap_data
  19. #define Color           scratch1::color
  20. #define Point           sb1::point
  21. #define Rect            sb1::rect
  22. #define Form            sb1::form
  23. #define ColorForm       sb1::form_color
  24.  
  25. Project read (InputStream input) {
  26.     if (readString(input, 8).compare("ScratchV")) throw NOT_A_SCRATCH_1_FILE;
  27.     String s = readString(input, 2);
  28.     if (s.compare("01") | s.compare("02")) throw BAD_FILE_VERSION;
  29.     readString(input, 4);
  30.     ObjectTable info = readObjectTable(input);
  31.     ObjectTable content = readObjectTable(input);
  32.     return build(info, content);
  33. }
  34.  
  35. Project read (ObjectTable info, ObjectTable content) {
  36.     Project project = Project();
  37.     if (info[0].getType() != 24) throw INFO_MAP_EXPECTED;
  38.     MapObject dict = reinterpret_cast<MapObject>(info[0]);
  39.     project.setThumbnail(readForm(dict.getAs("thumbnail", 34)));
  40.     project.setAuthor(dict.getAs("author", 9, 10, 14));
  41.     project.setVersion(dict.getAs("version", 9, 10, 14));
  42.     project.setProperty("language", dict["language"]);
  43.     project.setProperty("platform", dict["platform"]);
  44.     project.setProperty("history", dict["history"]);
  45.     project.setProperty("comment", dict["comment"]);
  46.     project.setProperty("os-version", dict["os-version"]);
  47.     if (content[0].getType() != 125) throw STAGE_EXPECTED;
  48.     double zoom = 1;
  49.     int xPan = 0, yPan = 0;
  50.     UserClassObject stage = ((UserClassObject) content[0]);
  51.     if (stage[12].isNumeric()) zoom = stage[12].getAsDouble();
  52.     if (stage[13].isNumeric()) xPan = stage[13].getAsInt();
  53.     if (stage[14].isNumeric()) yPan = stage[14].getAsInt();
  54.     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);
  55.     Rect outputSpace = Rect(-xPan, yPan, (480 - xPan) * zoom / 100, (360 + yPan) * zoom / 100);
  56.     project.setRenderTransform(inputSpace, outputSpace);
  57.     if (!stage[15].isNull()) printf("obsoleteSavedState property non-null");
  58.     project.setVolume(stage[17].isNumeric() ? stage[17].getAsDouble() : 1);
  59.     project.setTempo(stage[18].isNumeric() ? stage[18].getAsInt() : 60);
  60.     readSprites(stage[16], &project);
  61.     // TODO: sceneStates field, [19]
  62.     readLists(stage[20], &project);
  63.     if (stage.getAsReference(6, 99).dereference().isString() && stage.getAsReference(6, 99).dereference().getAsString().compare("Stage")) throw MALFORMED_STAGE;
  64.     project.setVariables(readVariables(stage[7]));
  65.     Stage s = Stage();
  66.     s.loadBlocks(readBlocks(stage[8]));
  67.     if (stage[9].isBool() && stage[9].getAsBool()) throw MALFORMED_STAGE;
  68.     s.loadMedia(readMedia(stage[10]));
  69.     if (stage[11].isNumeric()) s.costume = stage[11].getAsInt();
  70.     // TODO: color field, [3]; flags, [4]; properties, [5];
  71. }
  72.  
  73. Vector<Asset> readMedia (Object obj1) {
  74.     if (!obj1.isReference() || !reinterpret_cast<ObjectReference>(obj1).dereference().isArray()) throw MALFORMED_MEDIA;
  75.     Vector<Object> v = reinterpret_cast<ObjectReference>(obj1).dereference().getAsArray();
  76.     int i = v.size();
  77.     Vector<Asset> ret = Vector<Asset>(size);
  78.     for (int i = 0; i < size; i++)
  79.         ret[i] = readAsset(v[i]);
  80.     return ret;
  81. }
  82.  
  83. Asset readAsset (Object obj1) {
  84.     if (!obj1.isReference() || !reinterpret_cast<ObjectReference>(obj1).dereference().isUserClass()) throw MALFORMED_ASSET;
  85.     UserClassObject a = reinterpret_cast<ObjectReference>(obj1).dereference().getAsUserClass();
  86.     int type = a.getType();
  87.     switch (type) {
  88.         case 162:
  89.             Asset a = readForm(a.getAs(1, 34));
  90.  
  91. String readString (InputStream input, int size) {
  92.     char* s = new char[size];
  93.     input.read(s, size);
  94.     return String(s, size);
  95. }
  96.  
  97. unsigned short readShort (InputStream input) {
  98.     return reinterpret_cast<unsigned short>((input.get() << 8) | input.get());
  99. }
  100.  
  101. unsigned int readInt (InputStream input) {
  102.     return reinterpret_cast<unsigned int>((input.get() << 24) | (input.get() << 16) | (input.get() << 8) | input.get());
  103. }
  104.  
  105. int read24Bit (InputStream input) {
  106.     return (input.get() << 16) | (input.get() << 8) | input.get();
  107. }
  108.  
  109. unsigned long readLong (InputStream input) {
  110.     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());
  111. }
  112.  
  113. ObjectTable readObjectTable (InputStream input) {
  114.     if (readString(input, 10).compare("ObjS\0Stch\0")) throw NOT_AN_OBJECT_TABLE;
  115.     unsigned int len = readInt(input);
  116.     ObjectTable table = ObjectTable(len);
  117.     for (unsigned int i = 0; i < len; i++)
  118.         table[i] = readObject(input, false, &table);
  119.     return table;
  120. }
  121.  
  122. Object readObject (InputStream input, ObjectTable* table) {
  123.     Object tryInline = readInline(input, table);
  124.     if (tryInline) return tryInline;
  125.     if (type > 99) return readUserClass(input.seekg(input.tellg() - 1), table);
  126.     int type = input.get();
  127.     switch (type) {
  128.         case 9:
  129.         case 10:
  130.         case 11:
  131.         case 14:
  132.             return ConstantObject<String>(readString(input, readInt(input)));
  133.         case 12:
  134.             unsigned int length = readInt(input) * 2;
  135.             return ConstantObject<SoundData>(SoundData(readString(input).c_str(), length));
  136.         case 13:
  137.             unsigned int length = readInt(input) * 4;
  138.             return ConstantObject<BitmapData>(SoundData(readString(input).c_str(), length));
  139.         case 20:
  140.         case 21:
  141.         case 22:
  142.         case 23:
  143.             unsigned int length = readInt(input);
  144.             ArrayObject array = new ArrayObject(length);
  145.             for (unsigned int i = 0; i < length; i++)
  146.                 array[i] = readInline(input, table);
  147.             return array;
  148.         case 24:
  149.         case 25:
  150.             unsigned int length = readInt(input) * 2;
  151.             MapObject array = new MapObject(length);
  152.             for (unsigned int i = 0; i < length; i++)
  153.                 array.put(readInline(input, table), readInline(input, table));
  154.             return array;
  155.         case 30:
  156.         case 31:
  157.             unsigned int color = readInt(input);
  158.             short r = (color & 0x3FF00000) >> 20;
  159.             short g = (color & 0x000FFC00) >> 10;
  160.             short b = color & 0x000003FF;
  161.             int a = (type == 31) ? input.get() : 0xFF;
  162.             return ConstantObject<Color>(Color(r, g, b, a));
  163.         case 32:
  164.             return ConstantObject<Point>(Point(readInline(input, table), readInline(input, table)));
  165.         case 33:
  166.             return ConstantObject<Rect>(Rect(readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table)));
  167.         case 34:
  168.             return ConstantObject<Form>(Form(readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table)));
  169.         case 35:
  170.             return ConstantObject<ColorForm>(ColorForm(readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table), readInline(input, table)));
  171.         default:
  172.             throw UNKNOWN_FIXED_FORMAT_TYPE;
  173.     }
  174. }
  175.  
  176. Object readInline (InputStream input, ObjectTable* table) {
  177.     int type = input.get();
  178.     switch (type) {
  179.         case 1:
  180.             return ConstantObject.NIL;
  181.         case 2:
  182.             return ConstantObject.TRUE;
  183.         case 3:
  184.             return ConstantObject.FALSE;
  185.         case 4:
  186.             return ConstantObject<int>(reinterpret_cast<int>(readInt(input)));
  187.         case 5:
  188.             return ConstantObject<short>(reinterpret_cast<short>(readShort(input)));
  189.         case 6:
  190.         case 7:
  191.             unsigned short bytes = readShort(input);
  192.             return ConstantObject<LongInt>(LongInt(readString(input, bytes).c_str(), bytes, type == 7));
  193.         case 8:
  194.             return ConstantObject<double>(*(reinterpret_cast<double*>(&read_long(input))));
  195.         case 99:
  196.             return ObjectReference(read24Bit(input), table);
  197.         default:
  198.             input.seekg(input.tellg() - 1);
  199.             return NULL;
  200.     }
  201. }
  202.  
  203. Object readUserClass (InputStream input, ObjectTable* table) {
  204.     int type = input.get();
  205.     int version = input.get();
  206.     int fieldLength = input.get();
  207.     Vector<Object> fields = Vector<Object>(fieldLength);
  208.     for (int i = 0; i < fieldsLength; i++)
  209.         fields[i] = readInline(input, table);
  210.     return UserClassObject(type, version, fields);
  211. }
  212.  
  213. namespace scratch1 {
  214.     class object_table {
  215.         Object* objects;
  216.         unsigned int size;
  217.        
  218.         public:
  219.             object_table (unsigned int size) {
  220.                 this->objects = new Object[size];
  221.                 this->size = size;
  222.             }
  223.        
  224.             Object* operator [] (unsigned int access) {
  225.                 return this->objects[access];
  226.             }
  227.     }
Advertisement
Add Comment
Please, Sign In to add comment