fixed format warnings
[swftools.git] / src / swfcombine.c
index cc679f5..7daec9c 100644 (file)
@@ -40,11 +40,16 @@ struct config_t
    char cat;
    char merge;
    char isframe;
+   char local_with_networking;
+   char local_with_filesystem;
+   char accelerated_blit;
+   char hardware_gpu;
    int loglevel;
    int sizex;
    char hassizex;
    int sizey;
    char hassizey;
+   int flashversion;
    int framerate;
    int movex;
    int movey;
@@ -103,12 +108,14 @@ int args_callback_option(char*name,char*val) {
     }
     else if (!strcmp(name, "x"))
     {
-       config.movex = atoi(val);
+       float x = atof(val);
+       config.movex = (int)(x*20+0.5);
        return 1;
     }
     else if (!strcmp(name, "y"))
     {
-       config.movey = atoi(val);
+       float y = atof(val);
+       config.movey = (int)(y*20+0.5);
        return 1;
     }
     else if (!strcmp(name, "m"))
@@ -135,7 +142,7 @@ int args_callback_option(char*name,char*val) {
     {
 
        float rate = atof(val);
-       if ((rate < 1.0/256) ||(rate >= 256.0)) {
+       if ((rate < 0) ||(rate >= 256.0)) {
            fprintf(stderr, "Error: You must specify a valid framerate between 1/256 and 255.\n");
            exit(1);
        }
@@ -159,6 +166,36 @@ int args_callback_option(char*name,char*val) {
        config.scalex = config.scaley = atoi(val)/100.0;
        return 1;
     }
+    else if (!strcmp(name, "w"))
+    {
+       config.scalex = atoi(val)/100.0;
+       return 1;
+    }
+    else if (!strcmp(name, "h"))
+    {
+       config.scaley = atoi(val)/100.0;
+       return 1;
+    }
+    else if (!strcmp(name, "N"))
+    {
+       config.local_with_networking = 1;
+       return 0;
+    }
+    else if (!strcmp(name, "L"))
+    {
+       config.local_with_filesystem = 1;
+       return 0;
+    }
+    else if (!strcmp(name, "B"))
+    {
+       config.accelerated_blit = 1;
+       return 0;
+    }
+    else if (!strcmp(name, "G"))
+    {
+       config.hardware_gpu = 1;
+       return 0;
+    }
     else if (!strcmp(name, "t") || !strcmp(name, "T"))
     {
        if(master_filename) {
@@ -183,26 +220,30 @@ int args_callback_option(char*name,char*val) {
     }
 }
 
-struct options_t options[] =
-{{"o","output"},
- {"s","scale"},
- {"d","dummy"},
- {"x","xpos"},
- {"y","ypos"},
- {"X","width"},
- {"Y","height"},
- {"r","rate"},
- {"f","frame"},
- {"l","overlay"},
- {"m","merge"},
- {"t","stack"},
- {"T","stack1"},
- {"v","verbose"},
- {"V","version"},
- {"c","clip"},
- {"a","cat"},
- {"z","zlib"},
- {0,0}
+static struct options_t options[] = {
+{"o", "output"},
+{"t", "stack"},
+{"T", "stack1"},
+{"m", "merge"},
+{"a", "cat"},
+{"l", "overlay"},
+{"c", "clip"},
+{"v", "verbose"},
+{"F", "flashversion"},
+{"d", "dummy"},
+{"f", "frame"},
+{"x", "movex"},
+{"y", "movey"},
+{"s", "scale"},
+{"r", "rate"},
+{"X", "width"},
+{"Y", "height"},
+{"N", "local-with-networking"},
+{"G", "hardware-gpu"},
+{"B", "accelerated-blit"},
+{"L", "local-with-filesystem"},
+{"z", "zlib"},
+{0,0}
 };
 
 int args_callback_longoption(char*name,char*val) {
@@ -254,30 +295,51 @@ int args_callback_command(char*name, char*val) {
     return 0;
 }
 
-void args_callback_usage(char*name)
+void args_callback_usage(char *name)
 {
+    printf("\n");
     printf("Usage: %s [-rXYomlcv] [-f] masterfile [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN\n", name);
     printf("OR:    %s [-rXYomv] --stack[1] [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN\n", name);
     printf("OR:    %s [-rXYov] --cat [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN\n", name);
     printf("OR:    %s [-rXYomlcv] --dummy [-xys] [file]\n", name);
     printf("\n");
-    printf("-o outputfile       --output    explicitly specify output file. (otherwise, output.swf will be used)\n");
-    printf("-t                  --stack     place each slave in a seperate frame (no master movie)\n");
-    printf("-T                  --stack1    place each slave in the first frame (no master movie)\n");
-    printf("-m                  --merge     Don't store the slaves in Sprites/MovieClips\n");
-    printf("-a                  --cat       concatenate all slave files (no master movie)\n");
-    printf("-l                  --overlay   Don't remove any master objects, only overlay new objects\n");
-    printf("-c                  --clip      Clip the slave objects by the corresponding master objects\n");
-    printf("-v                  --verbose   Use more than one -v for greater effect \n");
-    printf("-d                  --dummy     Don't require slave objects \n");
-    printf("-f                  --frame     The following identifier is a frame or framelabel, not an id or objectname\n");
-    printf("-x xpos             --movex     x Adjust position of slave by xpos twips (1/20 pixel)\n");
-    printf("-y ypos             --movey     y Adjust position of slave by ypos twips (1/20 pixel)\n");
-    printf("-s scale            --scale     Adjust size of slave by scale%\n");
-    printf("-r framerate        --rate      Set movie framerate (frames/sec)\n");
-    printf("-X width            --width     Force movie width to scale (default: use master width (not with -t))\n");
-    printf("-Y height           --height    Force movie height to scale (default: use master height (not with -t))\n");
-    printf("-z zlib             --zlib      Enable Flash 6 (MX) Zlib Compression\n");
+    printf("-o , --output <outputfile>      explicitly specify output file. (otherwise, output.swf will be used)\n");
+    printf("-t , --stack                   place each slave in a seperate frame (no master movie)\n");
+    printf("-T , --stack1                  place each slave in the first frame (no master movie)\n");
+    printf("-m , --merge                   Don't store the slaves in Sprites/MovieClips\n");
+    printf("-a , --cat                     concatenate all slave files (no master movie)\n");
+    printf("-l , --overlay                 Don't remove any master objects, only overlay new objects\n");
+    printf("-c , --clip                    Clip the slave objects by the corresponding master objects\n");
+    printf("-v , --verbose                 Be verbose. Use more than one -v for greater effect \n");
+    printf("-F , --flashversion            Set the flash version of the output file.\n");
+    printf("-d , --dummy                   Don't require slave objects (for changing movie attributes)\n");
+    printf("-f , --frame                   The following identifier is a frame or framelabel, not an id or objectname\n");
+    printf("-x , --movex <xpos>            x Adjust position of slave by <xpos> pixels\n");
+    printf("-y , --movey <ypos>            y Adjust position of slave by <ypos> pixels\n");
+    printf("-s , --scale <scale>           Adjust size of slave by <scale> percent (e.g. 100%% = original size)\n");
+    printf("-r , --rate <fps>              Set movie framerate to <fps> (frames/sec)\n");
+    printf("-X , --width <width>           Force movie bbox width to <width> (default: use master width (not with -t))\n");
+    printf("-Y , --height <height>          Force movie bbox height to <height> (default: use master height (not with -t))\n");
+    printf("-N , --local-with-networking     Make output file \"local-with-networking\"\n");
+    printf("-G , --hardware-gpu            Set the \"use hardware gpu\" bit in the output file\n");
+    printf("-B , --accelerated-blit        Set the \"use accelerated blit\" bit in the output file\n");
+    printf("-L , --local-with-filesystem     Make output file \"local-with-filesystem\"\n");
+    printf("-z , --zlib <zlib>             Enable Flash 6 (MX) Zlib Compression\n");
+    printf("\n");
+}
+
+void removeCommonTags(SWF * swf)
+{
+    TAG*tag = swf->firstTag;
+    while(tag) {
+       if(tag->id == ST_SCENEDESCRIPTION ||
+          tag->id == ST_FILEATTRIBUTES ||
+          tag->id == ST_REFLEX) {
+           tag = swf_DeleteTag(swf, tag);
+       } else {
+           tag = tag->next;
+       }
+    }
 }
 
 static void makestackmaster(SWF*swf)
@@ -285,8 +347,9 @@ static void makestackmaster(SWF*swf)
     TAG*tag;
     int t;
     SRECT box;
-    int fileversion = 1;
+    int fileversion = config.zlib?6:3;
     int frameRate = 256;
+    U32 fileAttributes = 0;
     RGBA rgb;
     rgb.r=rgb.b=rgb.g=0;
     memset(&box, 0, sizeof(box));
@@ -303,6 +366,10 @@ static void makestackmaster(SWF*swf)
            exit(1);
        }
        close(fi);
+       swf_RemoveJPEGTables(&head);
+        fileAttributes |= head.fileAttributes;
+       removeCommonTags(&head);
+
        msg("<verbose> File %s has bounding box %d:%d:%d:%d\n",
                slave_filename[t], 
                head.movieSize.xmin, head.movieSize.ymin,
@@ -342,6 +409,7 @@ static void makestackmaster(SWF*swf)
     swf->fileVersion = fileversion;
     swf->movieSize = box;
     swf->frameRate = frameRate;
+    swf->fileAttributes = fileAttributes;
 
     swf->firstTag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
     tag = swf->firstTag;
@@ -378,6 +446,7 @@ static char* slavename = 0;
 static int slaveid = -1;
 static int slaveframe = -1;
 static char masterbitmap[65536];
+static char depthbitmap[65536];
 
 #define FLAGS_WRITEDEFINES 1
 #define FLAGS_WRITENONDEFINES 2
@@ -428,7 +497,7 @@ void jpeg_assert(SWF*master, SWF*slave)
        {
            // ok, both have jpegtables, but they're identical.
            // delete one and don't throw an error
-           swf_DeleteTag(spos);
+           swf_DeleteTag(slave, spos);
            spos = 0;
        }
     }
@@ -476,13 +545,19 @@ TAG* write_sprite_defines(TAG*tag, SWF*sprite)
                    case ST_SETBACKGROUNDCOLOR:
                       msg("<debug> deliberately ignoring BACKGROUNDCOLOR tag");
                       break;
+                   case ST_SHOWFRAME:
+                      msg("<debug> deliberately ignoring SHOWFRAME tag");
+                      break;
+                   case ST_REFLEX:
+                      msg("<debug> deliberately ignoring REFLEX tag");
+                      break;
                    case 40:
                    case 49:
                    case 51:
-                      msg("<notice> found tag %d. This is a Generator template, isn't it?", tag->id);
+                      msg("<notice> found tag %d. This is a Generator template, isn't it?", rtag->id);
                       break;
                    default:
-                      msg("<notice> funny tag: %d is neither defining nor sprite", tag->id);
+                      msg("<notice> funny tag: %d is neither defining nor sprite", rtag->id);
                }
            }
        }
@@ -493,7 +568,6 @@ TAG* write_sprite_defines(TAG*tag, SWF*sprite)
 
 void changedepth(TAG*tag, int add)
 {
-    /* fucking byteorders */
     if(tag->id == ST_PLACEOBJECT)
        PUT16(&tag->data[2],GET16(&tag->data[2])+add);
     if(tag->id == ST_PLACEOBJECT2)
@@ -502,6 +576,23 @@ void changedepth(TAG*tag, int add)
        PUT16(&tag->data[2],GET16(&tag->data[2])+add);
     if(tag->id == ST_REMOVEOBJECT2)
        PUT16(&tag->data[0],GET16(&tag->data[0])+add);
+    if(tag->id == ST_PLACEOBJECT2) {
+       SWFPLACEOBJECT obj;
+       U8 flags;
+       swf_SetTagPos(tag, 0);
+       flags = swf_GetU8(tag);
+       if(flags&2) swf_GetU16(tag); //id
+       if(flags&4) swf_GetMatrix(tag, 0);
+       if(flags&8) swf_GetCXForm(tag, 0,1);
+       if(flags&16) swf_GetU16(tag); //ratio
+       if(flags&64) {
+           swf_ResetReadBits(tag);
+           printf("%d->%d\n", GET16(&tag->data[tag->pos]),
+                              GET16(&tag->data[tag->pos])+add);
+           PUT16(&tag->data[tag->pos],GET16(&tag->data[tag->pos])+add);
+       }
+       msg("<warning> Depth relocation not fully working yet with clipdepths", tag->id);
+    }
 }
 
 void matrix_adjust(MATRIX*m, int movex, int movey, float scalex, float scaley, int scalepos)
@@ -520,7 +611,7 @@ void matrix_adjust(MATRIX*m, int movex, int movey, float scalex, float scaley, i
 
 void write_changepos(TAG*output, TAG*tag, int movex, int movey, float scalex, float scaley, int scalepos)
 {
-    if(movex || movey || scalex != 1 || scaley != 1)
+    if(movex || movey || scalex != 1.0 || scaley != 1.0)
     {
        switch(tag->id)
        {
@@ -547,7 +638,8 @@ void write_changepos(TAG*output, TAG*tag, int movex, int movey, float scalex, fl
                matrix_adjust(&m, movex, movey, scalex, scaley, scalepos);
                swf_SetMatrix(output, &m);
 
-               //swf_ResetReadBits(tag);
+               if (tag->readBit)  { tag->pos++; tag->readBit = 0; } //swf_ResetReadBits(tag);
+
                swf_SetBlock(output, &tag->data[tag->pos], tag->len - tag->pos);
                break;
            }
@@ -560,7 +652,8 @@ void write_changepos(TAG*output, TAG*tag, int movex, int movey, float scalex, fl
                matrix_adjust(&m, movex, movey, scalex, scaley, scalepos);
                swf_SetMatrix(output, &m);
                
-               //swf_ResetReadBits(tag);
+               if (tag->readBit)  { tag->pos++; tag->readBit = 0; } //swf_ResetReadBits(tag);
+
                swf_SetBlock(output, &tag->data[tag->pos], tag->len - tag->pos);
                break;
            }
@@ -612,8 +705,9 @@ TAG* write_sprite(TAG*tag, SWF*sprite, int spriteid, int replaceddefine)
                    rtag->id, rtag->len);
            tag = swf_InsertTag(tag, rtag->id);
            write_changepos(tag, rtag, config.movex, config.movey, config.scalex, config.scaley, 0);
-       
-           changedepth(tag, +2);
+
+           if(config.clip || (config.overlay && !config.isframe))
+               changedepth(tag, +2);
 
            if(tag->id == ST_SHOWFRAME)
            {
@@ -637,9 +731,10 @@ static char tag_ok_for_slave(int id)
 TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefine, int flags)
 {
     int outputslave = 0;
-    int frame = 0;
+    int frame = 1;
     int sframe = 0;
     int slavewritten = 0;
+    int deletedepth = -1;
 
     TAG* rtag = master->firstTag;
     TAG* stag = slave->firstTag;
@@ -656,7 +751,7 @@ TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefi
                }
                if(tag_ok_for_slave(stag->id)) {
                    tag = swf_InsertTag(tag, stag->id);
-                   swf_SetBlock(tag, stag->data, stag->len);
+                   write_changepos(tag, stag, config.movex, config.movey, config.scalex, config.scaley, 0);
                }
                stag = stag->next;
            }
@@ -664,6 +759,14 @@ TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefi
        if(rtag->id == ST_SHOWFRAME)
        {
            frame ++;
+           tag = swf_InsertTag(tag, ST_SHOWFRAME);
+            if(deletedepth>=0) {
+                tag = swf_InsertTag(tag, ST_REMOVEOBJECT2);
+                swf_SetU16(tag, deletedepth);
+                deletedepth=-1;
+            }
+           rtag = rtag->next;
+            continue;
        }
 
        if(swf_isDefiningTag(rtag) && (flags&FLAGS_WRITEDEFINES))
@@ -679,17 +782,19 @@ TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefi
                    swf_SetDefineID(tag, replaceddefine);
                } else {
                    /* don't write this tag */
-                   msg("<verbose> replacing tag %d id %d with sprite", rtag->id
-                           ,spriteid);
+                   msg("<verbose> replacing tag %d ID %d with sprite", rtag->id ,spriteid);
                }
 
                if(flags&FLAGS_WRITESPRITE)
                {
+                   msg("<debug> writing sprite defines");
                    tag = write_sprite_defines(tag, slave);
+                   msg("<debug> writing sprite");
                    tag = write_sprite(tag, slave, spriteid, replaceddefine);
                }
                if(flags&FLAGS_WRITESLAVE)
                {
+                   msg("<debug> writing slave");
                    outputslave = 1;
                }
            } else { 
@@ -697,7 +802,7 @@ TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefi
                swf_SetBlock(tag, rtag->data, rtag->len);
            }
        }
-       if(frame == slaveframe)
+       if(frame == slaveframe) /* only happens with config.isframe: put slave at specific frame */
        {
            if(flags&FLAGS_WRITESLAVE) {
                outputslave = 1;
@@ -706,7 +811,8 @@ TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefi
            if((flags&FLAGS_WRITESPRITE) && !slavewritten)
            {
                int id = get_free_id(masterbitmap);
-               int depth = 0;
+               int depth = 65535;
+               deletedepth = 65535;
                if(config.clip) {
                    msg("<fatal> Can't combine --clip and --frame");
                }
@@ -747,6 +853,7 @@ TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefi
                        rtag->id, rtag->len);
                tag = swf_InsertTag(tag, rtag->id);
                write_changepos(tag, rtag, config.mastermovex, config.mastermovey, config.masterscalex, config.masterscaley, 1);
+               
            }
        }
        rtag = rtag->next;
@@ -756,8 +863,9 @@ TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefi
     while(stag && stag->id!=ST_END)
     {
            if(tag_ok_for_slave(stag->id)) {
+               msg("<debug> [slave] write tag %02x (%d bytes in body), %.2f %.2f", rtag->id, rtag->len, config.movex /20.0, config.movey /20.0);
                tag = swf_InsertTag(tag, stag->id);
-               swf_SetBlock(tag, stag->data, stag->len);
+               write_changepos(tag, stag, config.movex, config.movey, config.scalex, config.scaley, 0);
            }
            stag = stag->next;
     }
@@ -786,6 +894,8 @@ void adjustheader(SWF*swf)
        swf->movieSize.ymax = 
        swf->movieSize.ymin + config.sizey;
     }
+    if(config.flashversion)
+       swf->fileVersion = config.flashversion;
 }
 
 void catcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
@@ -798,6 +908,8 @@ void catcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
        msg("<fatal> Can't combine --cat and --frame");
        exit(1);
     }
+    if(config.flashversion)
+       master->fileVersion = config.flashversion;
    
     tag = master->firstTag;
     while(tag)
@@ -877,9 +989,7 @@ void catcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
     }
     tag = swf_InsertTag(tag, ST_END);
 
-    tag = newswf->firstTag;
-    newswf->firstTag = newswf->firstTag->next; //remove temporary tag
-    swf_DeleteTag(tag);
+    swf_DeleteTag(newswf, tag);
 }
 
 void normalcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
@@ -889,24 +999,63 @@ void normalcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
     int frame = 0;
     char*framelabel;
     TAG * tag = master->firstTag;
+
+    memset(depthbitmap, 0, sizeof(depthbitmap));
     
     // set the idtab
     while(tag)
     {
+       int depth = swf_GetDepth(tag);
+       if(depth>=0) {
+           depthbitmap[depth] = 1;
+       }
        if(swf_isDefiningTag(tag)) {
            int defineid = swf_GetDefineID(tag);
            msg("<debug> tagid %02x defines object %d", tag->id, defineid);
            masterbitmap[defineid] = 1;
+
            if (!slavename && defineid==slaveid) {
                if(defineid>=0) {
                  spriteid = defineid;
                  msg("<notice> Slave file attached to object %d.", defineid);
                }
            }
+       } else if(tag->id == ST_EXPORTASSETS) {
+           int t;
+           int num = swf_GetU16(tag);
+           for(t=0;t<num;t++)
+           {
+               U16 id = swf_GetU16(tag);
+               char*name = swf_GetString(tag);
+               if(spriteid<0 && slavename && !strcmp(name,slavename)) {
+                   spriteid = id;
+                   msg("<notice> Slave file attached to object %d exported as %s.", id, name);
+               }
+           }
+       } else if(tag->id == ST_SYMBOLCLASS) {
+           /* a symbolclass tag is like a define tag: it defines id 0000 */
+           int num = swf_GetU16(tag);
+           int t;
+           for(t=0;t<num;t++) {
+               U16 id = swf_GetU16(tag);
+               if(!id) {
+                   masterbitmap[id] = 1;
+               }
+               swf_GetString(tag);
+           }
        } else if(tag->id == ST_PLACEOBJECT2) {
            char * name = swf_GetName(tag);
            int id = swf_GetPlaceID(tag);
 
+           {
+               SWFPLACEOBJECT obj;
+               swf_GetPlaceObject(tag, &obj);
+               swf_PlaceObjectFree(&obj);
+               if(obj.clipdepth) {
+                   depthbitmap[obj.clipdepth] = 1;
+               }
+           }
+
            if(name)
              msg("<verbose> tagid %02x places object %d named \"%s\"", tag->id, id, name);
            else
@@ -935,8 +1084,12 @@ void normalcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
 
     if (spriteid<0 && !config.isframe) {
        if(slavename) {
-           if(strcmp(slavename,"!!dummy!!"))
+           if(strcmp(slavename,"!!dummy!!")) {
                msg("<warning> Didn't find anything named %s in file. No substitutions will occur.", slavename);
+               if(!strcmp(slavename, "swf")) {
+                   msg("<warning> (If you were trying to combine rfxview with a document, try replacing 'swf' with 'viewport'.");
+               }
+           }
        }
        else
            msg("<warning> Didn't find id %d in file. No substitutions will occur.", slaveid);
@@ -944,6 +1097,9 @@ void normalcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
     }
 
     swf_Relocate (slave, masterbitmap);
+    
+    if(config.merge)
+       swf_RelocateDepth (slave, depthbitmap);
     jpeg_assert(slave, master);
     
     if (config.overlay)
@@ -973,9 +1129,7 @@ void normalcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
                FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES|   FLAGS_WRITESPRITE   );
     }
 
-    tag = newswf->firstTag;
-    newswf->firstTag = newswf->firstTag->next; //remove temporary tag
-    swf_DeleteTag(tag);
+    swf_DeleteTag(newswf, newswf->firstTag);
 }
 
 void combine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
@@ -984,6 +1138,11 @@ void combine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
     slaveid = -1;
     slaveframe = -1;
 
+    if(!master->fileVersion && slave)
+       master->fileVersion = slave->fileVersion;
+        
+    master->fileAttributes |= slave->fileAttributes;
+
     swf_FoldAll(master);
     swf_FoldAll(slave);
 
@@ -995,16 +1154,19 @@ void combine(SWF*master, char*slave_name, SWF*slave, SWF*newswf)
 
     if(config.isframe)
     {
-       int tmp;
-       if(slavename && slavename[0]!='#' && (sscanf(slavename, "%d", &tmp) ==
-               strlen(slavename))) {
-       /* if the name the slave should replace 
-          consists only of digits and the -f
-          option is given, it probably is not
-          a frame name but a frame number.
-        */
-           slaveid = tmp;
-           slavename = 0;
+       if(slavename && slavename[0]!='#') {
+           int tmp;
+           int len;
+           sscanf(slavename, "%d%n", &tmp, &len);
+           if(len == strlen(slavename)) {
+           /* if the name the slave should replace 
+              consists only of digits and the -f
+              option is given, it probably is not
+              a frame name but a frame number.
+            */
+               slaveid = tmp;
+               slavename = 0;
+           }
        }
 
        if(slaveid>=0) {
@@ -1075,6 +1237,11 @@ int main(int argn, char *argv[])
        msg("<error> Can't combine --cat and --merge");
        exit(1);
     }
+    
+    if(config.stack && config.cat) {
+       msg("<error> Can't combine --cat and --stack");
+       exit(1);
+    }
 
     if(config.stack) {
        if(config.overlay) {
@@ -1102,6 +1269,8 @@ int main(int argn, char *argv[])
            msg("<fatal> Failed to read from %s\n", master_filename);
            exit(1);
        }
+       swf_RemoveJPEGTables(&master);
+       removeCommonTags(&master);
        msg("<debug> Read %d bytes from masterfile\n", ret);
        close(fi);
     }
@@ -1169,30 +1338,54 @@ int main(int argn, char *argv[])
                }
                msg("<debug> Read %d bytes from slavefile\n", ret);
                close(fi);
+               swf_RemoveJPEGTables(&slave);
+               removeCommonTags(&slave);
            }
            else
            {
                memset(&slave, 0, sizeof(slave));
                slave.firstTag = swf_InsertTag(0, ST_END);
                slave.frameRate = 0;
-               slave.fileVersion = 4;
+               slave.fileVersion = 0;
                slave.frameCount = 0;
            }
 
            combine(&master, slave_name[t], &slave, &newswf);
            master = newswf;
        }
+       if(config.dummy && !config.hassizex && !config.hassizey && !config.mastermovex && !config.mastermovey) {
+           newswf.movieSize.xmin = newswf.movieSize.xmin*config.masterscalex;
+           newswf.movieSize.ymin = newswf.movieSize.ymin*config.masterscaley;
+           newswf.movieSize.xmax = newswf.movieSize.xmax*config.masterscalex;
+           newswf.movieSize.ymax = newswf.movieSize.ymax*config.masterscaley;
+       }
     }
 
+    if(!newswf.fileVersion)
+       newswf.fileVersion = 4;
+
+    if(config.local_with_filesystem)
+        newswf.fileAttributes &= ~FILEATTRIBUTE_USENETWORK;
+    if(config.local_with_networking)
+        newswf.fileAttributes |= FILEATTRIBUTE_USENETWORK;
+    if(config.accelerated_blit)
+        newswf.fileAttributes |= FILEATTRIBUTE_USEACCELERATEDBLIT;
+    if(config.hardware_gpu)
+        newswf.fileAttributes |= FILEATTRIBUTE_USEHARDWAREGPU;
+
     fi = open(outputname, O_BINARY|O_RDWR|O_TRUNC|O_CREAT, 0777);
 
-    if(config.zlib)
-       swf_WriteSWC(fi, &newswf);
-    else {
-       newswf.compressed = 0;
+    if(config.zlib) {
+       if(newswf.fileVersion < 6)
+           newswf.fileVersion = 6;
+        newswf.compressed = 1;
+       swf_WriteSWF(fi, &newswf);
+    } else {
+       newswf.compressed = -1; // don't compress
        swf_WriteSWF(fi, &newswf);
     }
     close(fi);
-    return 0;
+
+    return 0; //ok
 }