X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fcombine.c;h=4847a583e5c3046c55df2b3bbc9d3f09b51cacce;hb=22a49dfc00af6fc1b43057b44790f2087a09b6f2;hp=8547d37aa7c4c436855a9f9f7445aadd555b5814;hpb=1f2bb519aa0b3880fe6487c9a210db667d7ae273;p=swftools.git diff --git a/src/combine.c b/src/combine.c index 8547d37..4847a58 100644 --- a/src/combine.c +++ b/src/combine.c @@ -12,15 +12,14 @@ #include #include #include "../lib/log.h" +#include "../lib/rfxswf.h" #include "./flash.h" #include "./reloc.h" #include "./settings.h" -// TODO: -// * readers should be object-oriented - -static char* slavename; -static int slaveid; +static char* slavename = 0; +static int slaveid = -1; +static int slaveframe = -1; static char* tag_placeobject2_name (struct swf_tag* tag) { @@ -57,14 +56,58 @@ static int get_free_id() void changedepth(struct swf_tag*tag, int add) { + /* fucking big endian byte order */ if(tag->id == TAGID_PLACEOBJECT) - (*(u16*)&tag->data[2]) += add; + PUT16(&tag->data[2],GET16(&tag->data[2])+add); if(tag->id == TAGID_PLACEOBJECT2) - (*(u16*)&tag->data[1]) += add; + PUT16(&tag->data[1],GET16(&tag->data[1])+add); if(tag->id == TAGID_REMOVEOBJECT) - (*(u16*)&tag->data[2]) += add; + PUT16(&tag->data[2],GET16(&tag->data[2])+add); if(tag->id == TAGID_REMOVEOBJECT2) - (*(u16*)&tag->data[0]) += add; + PUT16(&tag->data[0],GET16(&tag->data[0])+add); +} + +void jpeg_assert() +{ + /* TODO: if there's a jpegtable found, store it + and handle it together with the flash file + headers */ + /* check that master and slave don't have both + jpegtables (which would be fatal) */ + int pos; + int mpos=-1, spos=-1; + pos = 0; + while(master.tags[pos].id != 0) + { + if(master.tags[pos].id == TAGID_JPEGTABLES) + mpos = pos; + pos++; + } + pos = 0; + while(master.tags[pos].id != 0) + { + if(slave.tags[pos].id == TAGID_JPEGTABLES) + spos = pos; + pos++; + } + if(spos>=0 && mpos>=0) + { + if(slave.tags[pos].length == + master.tags[pos].length && + !memcmp(slave.tags[pos].data, master.tags[pos].data, + master.tags[pos].length)) + { + // ok, both have jpegtables, but they're identical. + // delete one and don't make an error + for(;spos=0 && mpos>=0) { + logf(" Master and slave have incompatible JPEGTABLES."); + } } /* applies the config move and scale parameters to @@ -162,9 +205,9 @@ void write_sprite_defines(struct writer_t*w) break; } case TAGID_JPEGTABLES: - /* according to the flash specs, there may only - be one JPEGTABLES tag per swf. This is maybe - a big FIXME */ + /* if we get here, jpeg_assert has already run, + ensuring this is the only one of it's kind, + so we may safely write it out */ writer_write(w, tag->fulldata, tag->fulllength); break; case TAGID_EXPORTASSETS: @@ -190,7 +233,6 @@ void write_sprite_defines(struct writer_t*w) } } - void write_sprite(struct writer_t*w, int spriteid, int replaceddefine) { u16 tmp; @@ -199,7 +241,7 @@ void write_sprite(struct writer_t*w, int spriteid, int replaceddefine) u8*startpos; int pos = 0; // write slave(2) (header) - tmp = 0x3f + (TAGID_DEFINESPRITE << 6); + tmp = SWAP16(0x3f + (TAGID_DEFINESPRITE << 6)); writer_write(w, &tmp, 2); tagidpos = (u32*)writer_getpos(w); writer_write(w, &tmp32, 4); @@ -207,9 +249,9 @@ void write_sprite(struct writer_t*w, int spriteid, int replaceddefine) startpos = (u8*)writer_getpos(w); logf (" sprite id is %d", spriteid); - tmp = spriteid; + tmp = SWAP16(spriteid); writer_write(w, &tmp, 2); - tmp = slave.header.count; + tmp = SWAP16(slave.header.count); writer_write(w, &tmp, 2); @@ -218,26 +260,26 @@ void write_sprite(struct writer_t*w, int spriteid, int replaceddefine) logf(" %d frames to go",tmp); if(config.clip) { - tmp = 7 + (TAGID_PLACEOBJECT2 << 6); + tmp = SWAP16(7 + (TAGID_PLACEOBJECT2 << 6)); writer_write(w, &tmp, 2); - tmp = 2+64; //flags: character + clipaction + tmp = SWAP16(2+64); //flags: character + clipaction writer_write(w, &tmp, 1); - tmp = 0; //depth + tmp = SWAP16(0); //depth writer_write(w, &tmp,2); - tmp = replaceddefine; //id + tmp = SWAP16(replaceddefine); //id writer_write(w, &tmp,2); - tmp = 65535; //clipdepth + tmp = SWAP16(65535); //clipdepth writer_write(w, &tmp,2); } - if(config.overlay) { - tmp = 5 + (TAGID_PLACEOBJECT2 << 6); + if(config.overlay && !config.isframe) { + tmp = SWAP16(5 + (TAGID_PLACEOBJECT2 << 6)); writer_write(w, &tmp, 2); - tmp = 2; //flags: character + tmp = SWAP16(2); //flags: character writer_write(w, &tmp, 1); - tmp = 0; //depth + tmp = SWAP16(0); //depth writer_write(w, &tmp,2); - tmp = replaceddefine; //id + tmp = SWAP16(replaceddefine); //id writer_write(w, &tmp,2); } @@ -259,26 +301,55 @@ void write_sprite(struct writer_t*w, int spriteid, int replaceddefine) } while(slave.tags[pos++].id != TAGID_END); - *tagidpos = (u8*)writer_getpos(w) - startpos; // set length of sprite (in header) - logf(" sprite length is %d",*tagidpos); + PUT32(tagidpos, (u8*)writer_getpos(w) - startpos); // set length of sprite (in header) + logf(" sprite length is %d",GET32(tagidpos)); +} + +static char tag_ok_for_slave(int id) +{ + if(id == TAGID_BACKGROUNDCOLOR) + return 0; + return 1; } #define FLAGS_WRITEDEFINES 1 #define FLAGS_WRITENONDEFINES 2 #define FLAGS_WRITESPRITE 4 +#define FLAGS_WRITESLAVE 8 void write_master(struct writer_t*w, int spriteid, int replaceddefine, int flags) { int pos = 0; - do { - if(is_defining_tag(master.tags[pos].id) && (flags&1)) + int spos = 0; + int outputslave = 0; + int frame = 0; + int sframe = 0; + int slavewritten = 0; + while(master.tags[pos].id != 0) + { + if(master.tags[pos].id == TAGID_SHOWFRAME && outputslave) + { + while(slave.tags[spos].id) { + if(slave.tags[spos].id == TAGID_SHOWFRAME) { + spos++; + sframe++; + break; + } + if(tag_ok_for_slave(slave.tags[spos].id)) + writer_write(w, slave.tags[spos].fulldata, slave.tags[spos].fulllength); + spos++; + } + frame ++; + } + + if(is_defining_tag(master.tags[pos].id) && (flags&FLAGS_WRITEDEFINES)) { logf(" [master] write tag %02x (%d bytes in body)", master.tags[pos].id, master.tags[pos].length); - if( getidfromtag(&master.tags[pos]) == spriteid) + if(getidfromtag(&master.tags[pos]) == spriteid && !config.isframe) { if(config.overlay) { - *(u16*)master.tags[pos].data = replaceddefine; + PUT16(master.tags[pos].data, replaceddefine); writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength); } else { /* don't write this tag */ @@ -286,23 +357,85 @@ void write_master(struct writer_t*w, int spriteid, int replaceddefine, int flags ,spriteid); } - if(flags&4) + if(flags&FLAGS_WRITESPRITE) { write_sprite_defines(w); write_sprite(w, spriteid, replaceddefine); } + if(flags&FLAGS_WRITESLAVE) + { + outputslave = 1; + } } else { writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength); } } - if(!is_defining_tag(master.tags[pos].id) && (flags&2)) + if(frame == slaveframe) { - logf(" [master] write tag %02x (%d bytes in body)", - master.tags[pos].id, master.tags[pos].length); - writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength); + if(flags&FLAGS_WRITESLAVE) { + outputslave = 1; + slavewritten = 1; + } + if((flags&FLAGS_WRITESPRITE) && !slavewritten) + { + int id = get_free_id(); + int depth = 0; + char data[7]; + if(config.clip) { + logf(" Can't combine --clip and --frame"); + } + PUT16(&data[0], (u16)(TAGID_PLACEOBJECT2<<6) + 5); + *(u8*)&data[2]= 2; //flags: id + PUT16(&data[3], depth); + PUT16(&data[5], id); + write_sprite_defines(w); + write_sprite(w, id, -1); + writer_write(w,data,7); + slavewritten = 1; + } } + if(!is_defining_tag(master.tags[pos].id) && (flags&FLAGS_WRITENONDEFINES)) + { + int dontwrite = 0; + switch(master.tags[pos].id) { + case TAGID_PLACEOBJECT: + case TAGID_PLACEOBJECT2: + if(frame == slaveframe && !config.overlay) + dontwrite = 1; + case TAGID_REMOVEOBJECT: +// case TAGID_REMOVEOBJECT2: + /* place/removetags for the object we replaced + should be discarded, too, as the object to insert + isn't a sprite + */ + if(spriteid>=0 && getidfromtag(&master.tags[pos]) == spriteid && + !config.isframe && config.merge) + dontwrite = 1; + break; + } + if(!dontwrite) { + logf(" [master] write tag %02x (%d bytes in body)", + master.tags[pos].id, master.tags[pos].length); + writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength); + } + } + pos++; + } + + if(outputslave) + while(slave.tags[spos].id) + { + if(tag_ok_for_slave(slave.tags[spos].id)) + writer_write(w, slave.tags[spos].fulldata, slave.tags[spos].fulllength); + spos++; } - while(master.tags[pos++].id != 0); + if(!slavewritten && config.isframe && (flags&(FLAGS_WRITESLAVE|FLAGS_WRITESPRITE))) + { + logf(" Frame %d doesn't exist in file. No substitution will occur", + slaveframe); + } + //write END tag: + writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength); } void writeheader(struct writer_t*w, u8*data, int length) @@ -310,8 +443,9 @@ void writeheader(struct writer_t*w, u8*data, int length) if(config.hassizex || config.hassizey || config.framerate) { struct flash_header head; - swf_init(data-3, length+3); - head = swf_read_header(); + struct reader_t reader; + swf_init(&reader, data-3, length+3); + head = swf_read_header(&reader); if(config.hassizex) { head.boundingBox.x2 = head.boundingBox.x1 + config.sizex; @@ -335,13 +469,19 @@ uchar * catcombine(uchar*masterdata, int masterlength, char*_slavename, uchar*sl struct writer_t w; u32*headlength; u32 tmp32; - int length = masterlength + slavelength; + int length = masterlength*2 + slavelength; int pos = 0; + int t; + char* depths; uchar*newdata = malloc(length); if(!newdata) { logf(" Couldn't allocate %d bytes of memory", length); return 0; } + if(config.isframe) { + logf(" Can't combine --cat and --frame"); + exit(1); + } writer_init(&w, newdata, length); do { @@ -356,20 +496,66 @@ uchar * catcombine(uchar*masterdata, int masterlength, char*_slavename, uchar*sl swf_relocate (slavedata, slavelength, masterids); read_swf(&slave, slavedata, slavelength); + jpeg_assert(); writer_write(&w, "FWS",3); headlength = (u32*)(writer_getpos(&w) + 1); writeheader(&w, master.header.headerdata, master.header.headerlength); + depths = malloc(65536); + if(!depths) { + logf(" Couldn't allocate %d bytes of memory", 65536); + return 0; + } + memset(depths, 0, 65536); pos = 0; do { + int num=1; + u16 depth; logf(" [master] write tag %02x (%d bytes in body)", master.tags[pos].id, master.tags[pos].length); + switch(master.tags[pos].id) { + case TAGID_PLACEOBJECT2: + num++; + case TAGID_PLACEOBJECT: { + struct reader_t r; + reader_init (&r, master.tags[pos].data, master.tags[pos].length); + if(num>=2) + reader_readu8(&r); + depth = reader_readu16(&r); + depths[depth] = 1; + } + break; + case TAGID_REMOVEOBJECT: { + struct reader_t r; + reader_init (&r, master.tags[pos].data, master.tags[pos].length); + reader_readu16(&r); + depths[reader_readu16(&r)] = 0; + } + break; + case TAGID_REMOVEOBJECT2: { + struct reader_t r; + reader_init (&r, master.tags[pos].data, master.tags[pos].length); + depths[reader_readu16(&r)] = 0; + } + break; + } if(master.tags[pos].id != 0) writer_write(&w, master.tags[pos].fulldata, master.tags[pos].fulllength); } while(master.tags[pos++].id != 0); + for(t=0;t<65536;t++) + if(depths[t]) + { + char data[16]; + int len; + PUT16(&data[0], (TAGID_REMOVEOBJECT2<<6) + 2); + PUT16(&data[2], t); + writer_write(&w, data, 4); + } + free(depths); + pos = 0; do { logf(" [slave] write tag %02x (%d bytes in body)", @@ -380,7 +566,7 @@ uchar * catcombine(uchar*masterdata, int masterlength, char*_slavename, uchar*sl tmp32 = (u8*)writer_getpos(&w) - (u8*)newdata; //length *newlength = tmp32; - *headlength = tmp32; // set the header to the correct length + PUT32(headlength, tmp32); // set the header to the correct length return newdata; //length } @@ -395,6 +581,8 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar int spriteid = -1; int replaceddefine = -1; struct writer_t w; + int frame; + char*framelabel; length = masterlength + slavelength*2 + 128; // this is a guess, but a good guess. newdata = malloc(length); @@ -429,12 +617,22 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar logf(" Slave file attached to object %d.", id); } } + } else if(tag == TAGID_SHOWFRAME) { + if(slaveframe>=0 && frame==slaveframe) { + logf(" Slave file attached to frame %d.", frame); + } + frame++; + } else if(tag == TAGID_FRAMELABEL) { + char * name = master.tags[pos].data; + if(name && slavename && config.isframe && !strcmp(name, slavename)) { + slaveframe = frame; + logf(" Slave file attached to frame %d (%s).", frame, name); + } } } while(master.tags[pos++].id != 0); - if (spriteid<0) - { + if (spriteid<0 && !config.isframe) { if(slavename) { if(strcmp(slavename,"!!dummy!!")) logf(" Didn't find anything named %s in file. No substitutions will occur.", slavename); @@ -445,10 +643,10 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar } swf_relocate (slavedata, slavelength, masterids); - read_swf(&slave, slavedata, slavelength); + jpeg_assert(); - if(config.overlay) + if (config.overlay) replaceddefine = get_free_id(); // write file @@ -457,19 +655,26 @@ uchar * normalcombine(uchar*masterdata, int masterlength, char*_slavename, uchar headlength = (u32*)(writer_getpos(&w) + 1); writeheader(&w, master.header.headerdata, master.header.headerlength); - if(config.antistream) { + if (config.antistream) { + if (config.merge) { + logf(" Can't combine --antistream and --merge"); + } write_sprite_defines(&w); write_sprite(&w, spriteid, replaceddefine); write_master(&w, spriteid, replaceddefine, FLAGS_WRITEDEFINES); write_master(&w, spriteid, replaceddefine, FLAGS_WRITENONDEFINES); } else { - write_master(&w, spriteid, replaceddefine, + if (config.merge) + write_master(&w, spriteid, replaceddefine, + FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES|FLAGS_WRITESLAVE); + else + write_master(&w, spriteid, replaceddefine, FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES|FLAGS_WRITESPRITE); } tmp32 = (u8*)writer_getpos(&w) - (u8*)newdata; //length *newlength = tmp32; - *headlength = tmp32; // set the header to the correct length + PUT32(headlength, tmp32); return newdata; //length } @@ -479,16 +684,26 @@ uchar * combine(uchar*masterdata, int masterlength, char*_slavename, uchar*slave char master_flash = 0; char slave_flash = 0; slavename = _slavename; + + slaveid = -1; + slaveframe = -1; + if(slavename[0] == '#') { slaveid = atoi(&slavename[1]); slavename = 0; } + if(config.isframe) + { + slaveframe = slaveid; + slaveid = -1; + } logf(" move x (%d)", config.movex); logf(" move y (%d)", config.movey); - logf(" scale x (%d)", config.scalex); - logf(" scale y (%d)", config.scaley); + logf(" scale x (%f)", config.scalex); + logf(" scale y (%f)", config.scaley); + logf(" is frame (%d)", config.isframe); memset(masterids, -1, sizeof(masterids));