2 Implements combine(), which merges two swfs in memory.
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This file is distributed under the GPL, see file COPYING for details */
14 #include "../lib/log.h"
17 #include "./settings.h"
20 // * readers should be object-oriented
22 static char* slavename;
24 static char* tag_placeobject2_name (struct swf_tag* tag)
26 struct PlaceObject2 plo2;
27 placeobject2_init (&plo2, tag);
31 static u16 tag_placeobject2_character (struct swf_tag* tag)
33 struct PlaceObject2 plo2;
34 placeobject2_init (&plo2, tag);
38 static struct swffile master;
39 static struct swffile slave;
41 static int masterids[65536];
43 static int get_free_id()
48 if(masterids[t] == -1)
57 void changedepth(struct swf_tag*tag, int add)
59 if(tag->id == TAGID_PLACEOBJECT)
60 (*(u16*)&tag->data[2]) += add;
61 if(tag->id == TAGID_PLACEOBJECT2)
62 (*(u16*)&tag->data[1]) += add;
63 if(tag->id == TAGID_REMOVEOBJECT)
64 (*(u16*)&tag->data[2]) += add;
65 if(tag->id == TAGID_REMOVEOBJECT2)
66 (*(u16*)&tag->data[0]) += add;
69 /* applies the config move and scale parameters to
70 * a matrix. (If settings would provide a rotation,
71 * this would be a matrix concatenation/multiplication
72 * routine. In this case, it's just element-wise multiplication.
74 void matrix_adjust(struct MATRIX*m)
76 if(config.scalex != 1 || config.scaley != 1)
80 m->a[0][0] = config.scalex;
81 m->a[1][1] = config.scaley;
83 m->a[0][0] *= config.scalex;
84 m->a[1][1] *= config.scaley;
87 m->a[0][1] *= config.scalex;
88 m->a[1][0] *= config.scaley;
90 m->b[0] *= config.scalex;
91 m->b[1] *= config.scaley;
93 /* printf("hasscale: %d\n",m->hasscale);
94 printf("hasrotate: %d\n", m->hasrotate);
95 printf("move: %d %d\n", m->b[0],m->b[1]);
96 printf("rot: %f %f\n",m->a[0][0],m->a[0][1]);
97 printf(" %f %f\n",m->a[1][0],m->a[1][1]);*/
98 m->b[0] += config.movex;
99 m->b[1] += config.movey;
102 void write_changepos(struct swf_tag*tag, struct writer_t*w)
104 if(config.movex || config.movey || config.scalex != 1 || config.scaley != 1)
108 case TAGID_PLACEOBJECT: {
109 struct PlaceObject p;
110 placeobject_init(&p, tag);
111 matrix_adjust(&p.matrix);
112 placeobject_write(&p, w);
115 case TAGID_PLACEOBJECT2: {
116 struct PlaceObject2 p;
117 placeobject2_init(&p, tag);
120 MATRIX_init(&p.matrix);
122 matrix_adjust(&p.matrix);
123 placeobject2_write(&p, w);
127 writer_write(w, tag->fulldata, tag->fulllength);
132 writer_write(w, tag->fulldata, tag->fulllength);
136 void write_sprite_defines(struct writer_t*w)
139 while(slave.tags[pos].id != 0) {
140 struct swf_tag * tag = &slave.tags[pos];
141 if(!is_sprite_tag(tag->id)) {
142 logf("<debug> processing sprite tag %02x", slave.tags[pos].id);
143 if(is_defining_tag(tag->id))
145 logf("<debug> [sprite defs] write tag %02x (%d bytes in body)",
146 tag->id, tag->length);
147 writer_write(w, tag->fulldata, tag->fulllength);
152 {case TAGID_DEFINEFONTINFO:
154 /* define font info is not a defining tag, in that
155 * it doesn't define a new id, but rather extends
156 * an existing one. It also isn't a sprite tag.
157 * Anyway we can't throw it out, so we just pass it
162 case TAGID_EXPORTASSETS:
163 logf("<debug> deliberately ignoring EXPORTASSETS tag");
165 case TAGID_ENABLEDEBUGGER:
166 logf("<debug> deliberately ignoring ENABLEDEBUGGER tag");
168 case TAGID_BACKGROUNDCOLOR:
169 logf("<debug> deliberately ignoring BACKGROUNDCOLOR tag");
174 logf("<notice> found tag %d. This is a Generator template, isn't it?", slave.tags[pos].id);
177 logf("<notice> funny tag: %d is neither defining nor sprite", slave.tags[pos].id);
186 void write_sprite(struct writer_t*w, int spriteid, int replaceddefine)
193 // write slave(2) (header)
194 tmp = 0x3f + (TAGID_DEFINESPRITE << 6);
195 writer_write(w, &tmp, 2);
196 tagidpos = (u32*)writer_getpos(w);
197 writer_write(w, &tmp32, 4);
199 startpos = (u8*)writer_getpos(w);
203 logf("<warning> Didn't find anything named %s in file. No substitutions will occur.", slavename);
204 spriteid = get_free_id();
207 logf ("<notice> sprite id is %d", spriteid);
209 writer_write(w, &tmp, 2);
210 tmp = slave.header.count;
211 writer_write(w, &tmp, 2);
214 // write slave(2) (body)
215 tmp = slave.header.count;
216 logf("<debug> %d frames to go",tmp);
219 tmp = 7 + (TAGID_PLACEOBJECT2 << 6);
220 writer_write(w, &tmp, 2);
221 tmp = 2+64; //flags: character + clipaction
222 writer_write(w, &tmp, 1);
224 writer_write(w, &tmp,2);
225 tmp = replaceddefine; //id
226 writer_write(w, &tmp,2);
227 tmp = 65535; //clipdepth
228 writer_write(w, &tmp,2);
232 tmp = 5 + (TAGID_PLACEOBJECT2 << 6);
233 writer_write(w, &tmp, 2);
234 tmp = 2; //flags: character
235 writer_write(w, &tmp, 1);
237 writer_write(w, &tmp,2);
238 tmp = replaceddefine; //id
239 writer_write(w, &tmp,2);
243 struct swf_tag * tag = &slave.tags[pos];
244 if (is_sprite_tag(tag->id)) {
246 changedepth(tag, +1);
247 logf("<debug> [sprite main] write tag %02x (%d bytes in body)",
248 slave.tags[pos].id, slave.tags[pos].length);
249 write_changepos(tag, w);
251 if(tag->id == TAGID_SHOWFRAME)
254 logf("<debug> %d frames to go",tmp);
258 while(slave.tags[pos++].id != TAGID_END);
260 *tagidpos = (u8*)writer_getpos(w) - startpos; // set length of sprite (in header)
261 logf("<verbose> sprite length is %d",*tagidpos);
264 #define FLAGS_WRITEDEFINES 1
265 #define FLAGS_WRITENONDEFINES 2
266 #define FLAGS_WRITESPRITE 4
267 void write_master(struct writer_t*w, int spriteid, int replaceddefine, int flags)
271 if(is_defining_tag(master.tags[pos].id) && (flags&1))
273 logf("<debug> [master] write tag %02x (%d bytes in body)",
274 master.tags[pos].id, master.tags[pos].length);
275 if( getidfromtag(&master.tags[pos]) == spriteid)
279 *(u16*)master.tags[pos].data = replaceddefine;
280 writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength);
282 /* don't write this tag */
283 logf("<verbose> replacing tag %d id %d with sprite", master.tags[pos].id
289 write_sprite_defines(w);
290 write_sprite(w, spriteid, replaceddefine);
293 writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength);
296 if(!is_defining_tag(master.tags[pos].id) && (flags&2))
298 logf("<debug> [master] write tag %02x (%d bytes in body)",
299 master.tags[pos].id, master.tags[pos].length);
300 writer_write(w, master.tags[pos].fulldata, master.tags[pos].fulllength);
303 while(master.tags[pos++].id != 0);
307 uchar * combine(uchar*masterdata, int masterlength, char*_slavename, uchar*slavedata, int slavelength, int*newlength)
309 char master_flash = 0;
310 char slave_flash = 0;
311 slavename = _slavename;
313 logf("<debug> move x (%d)", config.movex);
314 logf("<debug> move y (%d)", config.movey);
315 logf("<debug> scale x (%d)", config.scalex);
316 logf("<debug> scale y (%d)", config.scaley);
318 memset(masterids, -1, sizeof(masterids));
322 logf("<fatal> the master file is too small (%d bytes)", masterlength);
327 logf("<fatal> the slave file is too small (%d bytes)", slavelength);
330 if(masterdata[2] == 'S' &&
331 masterdata[1] == 'W' &&
332 masterdata[0] == 'F')
334 logf("<notice> the master file is flash (swf) format\n");
337 if(slavedata[2] == 'S' &&
338 slavedata[1] == 'W' &&
341 logf("<notice> the slave file is flash (swf) format\n");
345 if(master_flash && slave_flash)
353 int replaceddefine = -1;
356 read_swf(&master, masterdata, masterlength);
358 length = masterlength + slavelength*2 + 128; // this is a guess, but a good guess.
359 newdata = malloc(length);
360 writer_init(&w, newdata, length);
363 logf("<fatal> Couldn't allocate %d bytes of memory", length);
370 int tag = master.tags[pos].id;
371 if(is_defining_tag(tag)) {
372 int defineid = getidfromtag(&master.tags[pos]);
373 logf("<debug> tagid %02x defines object %d", tag, defineid);
374 masterids[defineid] = 1;
375 } else if(tag == TAGID_PLACEOBJECT2) {
376 char * name = tag_placeobject2_name(&master.tags[pos]);
377 int id = tag_placeobject2_character(&master.tags[pos]);
380 logf("<verbose> tagid %02x places object %d named \"%s\"", tag, id, name);
382 logf("<verbose> tagid %02x places object %d (no name)", tag, id);
384 if (name && !strcmp(name,slavename)) {
387 logf("<notice> Slave file attached to object %d.", id);
392 while(master.tags[pos++].id != 0);
394 swf_relocate (slavedata, slavelength, masterids);
396 read_swf(&slave, slavedata, slavelength);
399 replaceddefine = get_free_id();
403 writer_write(&w, "FWS",3);
404 headlength = (u32*)(writer_getpos(&w) + 1);
405 writer_write(&w, master.header.headerdata, master.header.headerlength);
407 if(config.antistream) {
408 write_sprite_defines(&w);
409 write_sprite(&w, spriteid, replaceddefine);
410 write_master(&w, spriteid, replaceddefine, FLAGS_WRITEDEFINES);
411 write_master(&w, spriteid, replaceddefine, FLAGS_WRITENONDEFINES);
413 write_master(&w, spriteid, replaceddefine,
414 FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES|FLAGS_WRITESPRITE);
417 tmp32 = (u8*)writer_getpos(&w) - (u8*)newdata; //length
419 *headlength = tmp32; // set the header to the correct length
421 return newdata; //length