diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 13 | ||||
-rw-r--r-- | src/Makefile.in | 383 | ||||
-rw-r--r-- | src/args.h | 63 | ||||
-rw-r--r-- | src/bitio.c | 187 | ||||
-rw-r--r-- | src/bitio.h | 51 | ||||
-rw-r--r-- | src/combine.c | 398 | ||||
-rw-r--r-- | src/combine.h | 14 | ||||
-rw-r--r-- | src/flash.c | 528 | ||||
-rw-r--r-- | src/flash.h | 196 | ||||
-rw-r--r-- | src/reloc.c | 285 | ||||
-rw-r--r-- | src/reloc.h | 14 | ||||
-rw-r--r-- | src/settings.h | 26 | ||||
-rw-r--r-- | src/swfcombine.1 | 83 | ||||
-rw-r--r-- | src/swfcombine.c | 431 | ||||
-rw-r--r-- | src/swfdump.1 | 23 | ||||
-rw-r--r-- | src/swfdump.c | 109 | ||||
-rw-r--r-- | src/swfstrings.1 | 24 | ||||
-rw-r--r-- | src/swfstrings.c | 54 | ||||
-rw-r--r-- | src/types.h | 33 |
19 files changed, 2915 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000..6b50cee5 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,13 @@ +## Process this file with automake to produce Makefile.in +bin_PROGRAMS = swfcombine swfstrings swfdump +swfdump_SOURCES = swfdump.c +swfcombine_SOURCES = bitio.c bitio.h reloc.c reloc.h combine.c combine.h flash.c flash.h swfcombine.c types.h +swfstrings_SOURCES = swfstrings.c +swfdump_LINK = $(CCLD) ../lib/rfxswf.o -o $@ +swfcombine_LINK = $(CCLD) ../lib/log.o -o $@ +swfstrings_LINK = $(CCLD) ../lib/log.o ../lib/rfxswf.o -o $@ +##LIBS = +##swfcombine_LIBS = +##swfstrings_LIBS = -ljpeg +man_MANS = swfcombine.1 swfstrings.1 swfdump.1 + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 00000000..d87977be --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,383 @@ +# Makefile.in generated automatically by automake 1.4-p4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +EXEEXT = @EXEEXT@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ + +bin_PROGRAMS = swfcombine swfstrings swfdump +swfdump_SOURCES = swfdump.c +swfcombine_SOURCES = bitio.c bitio.h reloc.c reloc.h combine.c combine.h flash.c flash.h swfcombine.c types.h +swfstrings_SOURCES = swfstrings.c +swfdump_LINK = $(CCLD) ../lib/rfxswf.o -o $@ +swfcombine_LINK = $(CCLD) ../lib/log.o -o $@ +swfstrings_LINK = $(CCLD) ../lib/log.o ../lib/rfxswf.o -o $@ +man_MANS = swfcombine.1 swfstrings.1 swfdump.1 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +bin_PROGRAMS = swfcombine$(EXEEXT) swfstrings$(EXEEXT) swfdump$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +swfcombine_OBJECTS = bitio.o reloc.o combine.o flash.o swfcombine.o +swfcombine_LDADD = $(LDADD) +swfcombine_DEPENDENCIES = +swfcombine_LDFLAGS = +swfstrings_OBJECTS = swfstrings.o +swfstrings_LDADD = $(LDADD) +swfstrings_DEPENDENCIES = +swfstrings_LDFLAGS = +swfdump_OBJECTS = swfdump.o +swfdump_LDADD = $(LDADD) +swfdump_DEPENDENCIES = +swfdump_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +man1dir = $(mandir)/man1 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/bitio.P .deps/combine.P .deps/flash.P .deps/reloc.P \ +.deps/swfcombine.P .deps/swfdump.P .deps/swfstrings.P +SOURCES = $(swfcombine_SOURCES) $(swfstrings_SOURCES) $(swfdump_SOURCES) +OBJECTS = $(swfcombine_OBJECTS) $(swfstrings_OBJECTS) $(swfdump_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +swfcombine$(EXEEXT): $(swfcombine_OBJECTS) $(swfcombine_DEPENDENCIES) + @rm -f swfcombine$(EXEEXT) + $(swfcombine_LINK) $(swfcombine_LDFLAGS) $(swfcombine_OBJECTS) $(swfcombine_LDADD) $(LIBS) + +swfstrings$(EXEEXT): $(swfstrings_OBJECTS) $(swfstrings_DEPENDENCIES) + @rm -f swfstrings$(EXEEXT) + $(swfstrings_LINK) $(swfstrings_LDFLAGS) $(swfstrings_OBJECTS) $(swfstrings_LDADD) $(LIBS) + +swfdump$(EXEEXT): $(swfdump_OBJECTS) $(swfdump_DEPENDENCIES) + @rm -f swfdump$(EXEEXT) + $(swfdump_LINK) $(swfdump_LDFLAGS) $(swfdump_OBJECTS) $(swfdump_LDADD) $(LIBS) + +install-man1: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done + +uninstall-man1: + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man1 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-binPROGRAMS +install-exec: install-exec-am + +install-data-am: install-man +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-binPROGRAMS uninstall-man +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) $(MANS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-depend mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-binPROGRAMS clean-compile clean-tags clean-depend \ + clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \ + distclean-depend distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile install-man1 uninstall-man1 install-man \ +uninstall-man tags mostlyclean-tags distclean-tags clean-tags \ +maintainer-clean-tags distdir mostlyclean-depend distclean-depend \ +clean-depend maintainer-clean-depend info-am info dvi-am dvi check \ +check-am installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/args.h b/src/args.h new file mode 100644 index 00000000..a5699df4 --- /dev/null +++ b/src/args.h @@ -0,0 +1,63 @@ +/* args.h + Routines to simplify argument handling + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#ifndef __args_h__ +#define __args_h__ + +extern int args_callback_option(char*,char*); +extern int args_callback_longoption(char*,char*); +extern int args_callback_command(char*,char*); +extern void args_callback_usage(char*name); + +int argn; +char**argv; + +void processargs(int argn2,char**argv2) +{ + int t; + if(argn2==1) + { + args_callback_usage(argv2[0]); + exit(1); + } + for(t=1;t<argn2;t++) + { + char*next; + if(t<argn2-1) next=argv2[t+1]; + else next=0; + + if(argv2[t][0]=='-') + { + if(argv2[t][1]=='-') + { + if(!strcmp(&argv2[t][2],"help")) + { + args_callback_usage(argv2[0]); + exit(1); + } + t+=args_callback_longoption(&argv2[t][2],next); + } + else + { + if(strchr("?h",argv2[t][1])) + { + args_callback_usage(argv2[0]); + exit(1); + } + t+=args_callback_option(&argv2[t][1],next); + } + } + else + { + t+=args_callback_command(argv2[t],next); + } + } +} + +#endif //__args_h__ diff --git a/src/bitio.c b/src/bitio.c new file mode 100644 index 00000000..871fb804 --- /dev/null +++ b/src/bitio.c @@ -0,0 +1,187 @@ +/* bitio.c + Various routines for reading and writing bit- and bytewise, from and to memory. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#include "bitio.h" + +static uchar*data; +static int datalength; +static int datapos; + +void resetbits(); + +void reader_init(uchar*newdata, int newlength) +{ + data = newdata; + datalength = newlength; + datapos = 0; + resetbits(); +} +void skip(int length) +{ + datapos += length; +} +static u8 bitpos=8,mybyte; +static u8 bitmem=0; +void resetbits() +{ + bitpos=8; +} + +void input1(void*target) +{ + *(uchar*)target = *(uchar*)&data[datapos]; + datapos ++; +} +void input2(void*target) +{ + *(unsigned short int*)target = *(unsigned short int*)&data[datapos]; + datapos += 2; +} +void input4(void*target) +{ + *(unsigned int*)target = *(unsigned int*)&data[datapos]; + datapos += 4; +} +uchar*getinputpos() +{ + return &data[datapos]; +} +int getinputlength() +{ + return datalength; +} +void setinputpos(uchar*pos) +{ + datapos = pos-data; +} + +u32 readbit() +{ + if(bitpos==8) + { + bitpos=0; + input1(&mybyte); + } + return (mybyte>>(7-bitpos++))&1; +} +void readbits(u32*val,int num) +{ + int t; + *val=0; + for(t=0;t<num;t++) + { + *val<<=1; + *val|=readbit(); + } +} + +void readsbits(s32*val,int num) +{ + u32 x; + readbits(&x, num); + if((x>>(num-1))&1) + { + x|=(0xffffffff<<num); + } + *(s32*)val=x; +} + +u32 getbits(int num) +{ + u32 x; + readbits(&x,num); + return x; +} + +s32 getsbits(int num) +{ + s32 x; + readsbits(&x,num); + return x; +} + +u16 readu8() +{ + u8 a; + input1(&a); + return a; +} + +u16 readu16() +{ + u8 a,b; + // I'm not using input2(&a) here because our input is + // little endian. + input1(&a); + input1(&b); + return ((u16)b)*256+a; +} + +void writer_init(struct writer_t*w, u8*data, int maxlength) +{ + w->data = data; + w->maxlength = maxlength; + w->pos = 0; + w->bitpos = 0; + w->mybyte = 0; +} + +void writer_write(struct writer_t*w, void*data, int length) +{ + memcpy(&w->data[w->pos], data, length); + w->pos += length; +} + +void writer_writeu8(struct writer_t*w, u8 value) +{ + writer_resetbits(w); + writer_write(w, &value, 1); +} + +void writer_writeu16(struct writer_t*w, u16 value) +{ + writer_resetbits(w); + writer_write(w, &value, 2); +} + +void* writer_getpos(struct writer_t*w) +{ + return &w->data[w->pos]; +} + +void writer_resetbits(struct writer_t*w) +{ + if(w->bitpos) + writer_write(w, &w->mybyte, 1); + w->bitpos = 0; + w->mybyte = 0; +} + +void writer_writebit(struct writer_t*w, int bit) +{ + if(w->bitpos==8) + { + writer_write(w, &w->mybyte, 1); + w->bitpos = 0; + w->mybyte = 0; + } + if(bit&1) + w->mybyte |= 1 << (7 - w->bitpos); + w->bitpos ++; +} + +void writer_writebits(struct writer_t*w, u32 data, int bits) +{ + int t; + for(t=0;t<bits;t++) + { + writer_writebit(w, (data >> (bits-t-1))&1); + } +} + diff --git a/src/bitio.h b/src/bitio.h new file mode 100644 index 00000000..c9ec2383 --- /dev/null +++ b/src/bitio.h @@ -0,0 +1,51 @@ +/* bitio.h + Header file for bitio.c. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#ifndef __bitio_h__ +#define __bitio_h__ + +#include "types.h" + +void resetbits(); +void reader_init(uchar*newdata, int newlength); +void skip(int length); +void input1(void*target); +void input2(void*target); +void input4(void*target); + +uchar*getinputpos(); +int getinputlength(); +void setinputpos(uchar*pos); + +u32 readbit(); +void readbits(u32*val,int num); +void readsbits(s32*val,int num); +u32 getbits(int num); +s32 getsbits(int num); +u16 readu8(); +u16 readu16(); + +struct writer_t { + u8* data; + int maxlength; + int pos; + int bitpos; + u8 mybyte; +}; + +void writer_init(struct writer_t*w, u8*data, int maxlength); +void writer_write(struct writer_t*w, void*data, int length); +void* writer_getpos(struct writer_t*w); +void writer_writebit(struct writer_t*w, int bit); +void writer_writebits(struct writer_t*w, u32 data, int bits); +void writer_writeu8(struct writer_t*w, u8 value); +void writer_writeu16(struct writer_t*w, u16 value); +void writer_resetbits(struct writer_t*w); + +#endif //__bitio_h__ diff --git a/src/combine.c b/src/combine.c new file mode 100644 index 00000000..a6120066 --- /dev/null +++ b/src/combine.c @@ -0,0 +1,398 @@ +/* combine.c + Implements combine(), which merges two swfs in memory. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <memory.h> +#include "../lib/log.h" +#include "./flash.h" +#include "./reloc.h" +#include "./settings.h" + +// TODO: +// * readers should be object-oriented + +static char* tag_placeobject2_name (struct swf_tag* tag) +{ + struct PlaceObject2 plo2; + placeobject2_init (&plo2, tag); + return plo2.name; +} + +static u16 tag_placeobject2_character (struct swf_tag* tag) +{ + struct PlaceObject2 plo2; + placeobject2_init (&plo2, tag); + return plo2.id; +} + +static struct swffile master; +static struct swffile slave; + +static int masterids[65536]; + +static int get_free_id() +{ + int t; + for (t=1;t<65536;t++) + { + if(masterids[t] == -1) + { + masterids[t] = 1; + return t; + } + } + return -1; +} + +void changedepth(struct swf_tag*tag, int add) +{ + if(tag->id == TAGID_PLACEOBJECT) + (*(u16*)&tag->data[2]) += add; + if(tag->id == TAGID_PLACEOBJECT2) + (*(u16*)&tag->data[1]) += add; + if(tag->id == TAGID_REMOVEOBJECT) + (*(u16*)&tag->data[2]) += add; + if(tag->id == TAGID_REMOVEOBJECT2) + (*(u16*)&tag->data[0]) += add; +} + +/* applies the config move and scale parameters to + * a matrix. (If settings would provide a rotation, + * this would be a matrix concatenation/multiplication + * routine. In this case, it's just element-wise multiplication. + */ +void matrix_adjust(struct MATRIX*m) +{ + if(config.scalex != 1 || config.scaley != 1) + { + if(!m->hasscale) { + m->hasscale = 1; + m->a[0][0] = config.scalex; + m->a[1][1] = config.scaley; + } else { + m->a[0][0] *= config.scalex; + m->a[1][1] *= config.scaley; + } + if(m->hasrotate) { + m->a[0][1] *= config.scalex; + m->a[1][0] *= config.scaley; + } + m->b[0] *= config.scalex; + m->b[1] *= config.scaley; + } +/* printf("hasscale: %d\n",m->hasscale); + printf("hasrotate: %d\n", m->hasrotate); + printf("move: %d %d\n", m->b[0],m->b[1]); + printf("rot: %f %f\n",m->a[0][0],m->a[0][1]); + printf(" %f %f\n",m->a[1][0],m->a[1][1]);*/ + m->b[0] += config.movex; + m->b[1] += config.movey; +} + +void write_changepos(struct swf_tag*tag, struct writer_t*w) +{ + if(config.movex || config.movey || config.scalex != 1 || config.scaley != 1) + { + switch(tag->id) + { + case TAGID_PLACEOBJECT: { + struct PlaceObject p; + placeobject_init(&p, tag); + matrix_adjust(&p.matrix); + placeobject_write(&p, w); + break; + } + case TAGID_PLACEOBJECT2: { + struct PlaceObject2 p; + placeobject2_init(&p, tag); + if(!p.hasmatrix) { + p.hasmatrix = 1; + MATRIX_init(&p.matrix); + } + matrix_adjust(&p.matrix); + placeobject2_write(&p, w); + break; + } + default: + writer_write(w, tag->fulldata, tag->fulllength); + } + } + else + { + writer_write(w, tag->fulldata, tag->fulllength); + } +} + +uchar * combine(uchar*masterdata, int masterlength, char*slavename, uchar*slavedata, int slavelength, int*newlength) +{ + char master_flash = 0; + char slave_flash = 0; + + logf("<debug> move x (%d)", config.movex); + logf("<debug> move y (%d)", config.movey); + logf("<debug> scale x (%d)", config.scalex); + logf("<debug> scale y (%d)", config.scaley); + + memset(masterids, -1, sizeof(masterids)); + + if(masterlength < 3) + { + logf("<fatal> the master file is too small (%d bytes)", masterlength); + return 0; + } + if(slavelength < 3) + { + logf("<fatal> the slave file is too small (%d bytes)", slavelength); + return 0; + } + if(masterdata[2] == 'S' && + masterdata[1] == 'W' && + masterdata[0] == 'F') + { + logf("<notice> the master file is flash (swf) format\n"); + master_flash = 1; + } + if(slavedata[2] == 'S' && + slavedata[1] == 'W' && + slavedata[0] == 'F') + { + logf("<notice> the slave file is flash (swf) format\n"); + slave_flash = 1; + } + + if(master_flash && slave_flash) + { + int length; + int pos=0; + u16 tmp; + u32 tmp32; + u32*tagidpos; + u8*startpos; + u32*headlength; + uchar*newdata; + int spriteid = -1; + int replaceddefine = -1; + struct writer_t w; + + read_swf(&master, masterdata, masterlength); + + length = masterlength + slavelength*2 + 128; // this is a guess, but a good guess. + newdata = malloc(length); + writer_init(&w, newdata, length); + + if(!newdata) { + logf("<fatal> Couldn't allocate %d bytes of memory", length); + return 0; + } + + // set the idtab + pos = 0; + do { + int tag = master.tags[pos].id; + if(is_defining_tag(tag)) { + int defineid = getidfromtag(&master.tags[pos]); + logf("<debug> tagid %02x defines object %d", tag, defineid); + masterids[defineid] = 1; + } else if(tag == TAGID_PLACEOBJECT2) { + char * name = tag_placeobject2_name(&master.tags[pos]); + int id = tag_placeobject2_character(&master.tags[pos]); + + if(name) + logf("<verbose> tagid %02x places object %d named \"%s\"", tag, id, name); + else + logf("<verbose> tagid %02x places object %d (no name)", tag, id); + + if (name && !strcmp(name,slavename)) { + if(id>=0) { + spriteid = id; + logf("<notice> Slave file attached to object %d.", id); + } + } + } + } + while(master.tags[pos++].id != 0); + + swf_relocate (slavedata, slavelength, masterids); + + read_swf(&slave, slavedata, slavelength); + + // write header + + writer_write(&w, "FWS",3); + headlength = (u32*)(writer_getpos(&w) + 1); + writer_write(&w, master.header.headerdata, master.header.headerlength); + + // write sprite(1) + + pos = 0; + while(slave.tags[pos].id != 0) { + struct swf_tag * tag = &slave.tags[pos]; + if(!is_sprite_tag(tag->id)) { + logf("<debug> processing sprite tag %02x", slave.tags[pos].id); + if(is_defining_tag(tag->id)) + { + logf("<debug> [sprite defs] write tag %02x (%d bytes in body)", + tag->id, tag->length); + writer_write(&w, tag->fulldata, tag->fulllength); + } + else + { + switch(tag->id) + {case TAGID_DEFINEFONTINFO: + { + /* define font info is not a defining tag, in that + * it doesn't define a new id, but rather extends + * an existing one. It also isn't a sprite tag. + * Anyway we can't throw it out, so we just pass it + * through. + */ + break; + } + case TAGID_EXPORTASSETS: + logf("<debug> deliberately ignoring EXPORTASSETS tag"); + break; + case TAGID_ENABLEDEBUGGER: + logf("<debug> deliberately ignoring ENABLEDEBUGGER tag"); + break; + case TAGID_BACKGROUNDCOLOR: + logf("<debug> deliberately ignoring BACKGROUNDCOLOR tag"); + break; + case 40: + case 49: + case 51: + logf("<notice> found tag %d. This is a Generator template, isn't it?", slave.tags[pos].id); + break; + default: + logf("<notice> funny tag: %d is neither defining nor sprite", slave.tags[pos].id); + } + } + } + pos++; + } + + // write master (1) + pos = 0; + do { + if(is_defining_tag(master.tags[pos].id)) + { + logf("<debug> [master] write tag %02x (%d bytes in body)", + master.tags[pos].id, master.tags[pos].length); + if( getidfromtag(&master.tags[pos]) == spriteid) + { + if(config.overlay) + { + *(u16*)master.tags[pos].data = replaceddefine = get_free_id(); + writer_write(&w, master.tags[pos].fulldata, master.tags[pos].fulllength); + } else { + /* don't write this tag */ + logf("<verbose> replacing tag %d id %d with sprite", master.tags[pos].id + ,spriteid); + } + } else { + writer_write(&w, master.tags[pos].fulldata, master.tags[pos].fulllength); + } + } + } + while(master.tags[pos++].id != 0); + + // write slave(2) (header) + tmp = 0x3f + (TAGID_DEFINESPRITE << 6); + writer_write(&w, &tmp, 2); + tagidpos = (u32*)writer_getpos(&w); + writer_write(&w, &tmp32, 4); + + startpos = (u8*)writer_getpos(&w); + + if (spriteid<0) + { + logf("<warning> Didn't find anything named %s in file. No substitutions will occur.", slavename); + spriteid = get_free_id(); + } + + logf ("<notice> sprite id is %d", spriteid); + tmp = spriteid; + writer_write(&w, &tmp, 2); + tmp = slave.header.count; + writer_write(&w, &tmp, 2); + + + // write slave(2) (body) + pos = 0; + tmp = slave.header.count; + logf("<debug> %d frames to go",tmp); + + if(config.clip) { + tmp = 7 + (TAGID_PLACEOBJECT2 << 6); + writer_write(&w, &tmp, 2); + tmp = 2+64; //flags: character + clipaction + writer_write(&w, &tmp, 1); + tmp = 0; //depth + writer_write(&w, &tmp,2); + tmp = replaceddefine; //id + writer_write(&w, &tmp,2); + tmp = 65535; //clipdepth + writer_write(&w, &tmp,2); + } + + if(config.overlay) { + tmp = 5 + (TAGID_PLACEOBJECT2 << 6); + writer_write(&w, &tmp, 2); + tmp = 2; //flags: character + writer_write(&w, &tmp, 1); + tmp = 0; //depth + writer_write(&w, &tmp,2); + tmp = replaceddefine; //id + writer_write(&w, &tmp,2); + } + + do { + struct swf_tag * tag = &slave.tags[pos]; + if (is_sprite_tag(tag->id)) { + + changedepth(tag, +1); + logf("<debug> [sprite main] write tag %02x (%d bytes in body)", + slave.tags[pos].id, slave.tags[pos].length); + write_changepos(tag, &w); + + if(tag->id == TAGID_SHOWFRAME) + { + tmp--; + logf("<debug> %d frames to go",tmp); + } + } + } + while(slave.tags[pos++].id != TAGID_END); + + *tagidpos = (u8*)writer_getpos(&w) - startpos; // set length of sprite (in header) + logf("<verbose> sprite length is %d",*tagidpos); + + // write master (2) + pos = 0; + do { + if(!is_defining_tag(master.tags[pos].id)) + { + logf("<debug> [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); + } + } + while(master.tags[pos++].id != 0); + + tmp32 = (u8*)writer_getpos(&w) - (u8*)newdata; //length + *newlength = tmp32; + *headlength = tmp32; // set the header to the correct length + + return newdata; //length + } + + *newlength = 0; + return 0; +} diff --git a/src/combine.h b/src/combine.h new file mode 100644 index 00000000..d522771d --- /dev/null +++ b/src/combine.h @@ -0,0 +1,14 @@ +/* combine.h + Header file for combine.c + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#ifndef __combine_h__ +#define __combine_h__ +unsigned char * combine(unsigned char*masterdata, int masterlength, + char*slavename, unsigned char*slavedata, int slavelength, int*newlength); +#endif //__combine_h__ diff --git a/src/flash.c b/src/flash.c new file mode 100644 index 00000000..fff82843 --- /dev/null +++ b/src/flash.c @@ -0,0 +1,528 @@ +/* flash.c + Various routines for reading and writing swf files and tags. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#include "flash.h" +#include "bitio.h" + +void swf_init(uchar*newdata, int newlength) +{ + reader_init (&newdata[3], newlength - 3); +} + +struct flash_header swf_read_header() +{ + struct flash_header head; + u16 rate; + u16 count; + char version; + int length; + u8* oldpos = getinputpos(); + + input1(&version); + head.version = version; + input4(&length); + head.length = length; + + resetbits(); + head.boundingBox = readRECT(); + input2(&rate); + head.rate = rate; + input2(&count); + head.count = count; + + head.headerlength = getinputpos() - oldpos; + head.headerdata = oldpos; + + return head; +} + +struct RGB readRGB() +{ + struct RGB rgb; + input1(&rgb.r); + input1(&rgb.g); + input1(&rgb.b); + return rgb; +} + +struct RGBA readRGBA() +{ + struct RGBA rgba; + input1(&rgba.r); + input1(&rgba.g); + input1(&rgba.b); + input1(&rgba.a); + return rgba; +} + +struct GRADIENT readGRADIENT(int shape) +{ + struct GRADIENT gradient; + int t; + gradient.num = readu8(); + for(t=0;t<gradient.num;t++) + { + gradient.ratios[t] = readu8(); + if(shape>=3) + gradient.rgb[t] = readRGB(); + else + gradient.rgba[t] = readRGBA(); + } +} + +struct RECT readRECT() +{ + u32 a; + struct RECT r; + s32 b; + readbits(&a,5); + readsbits(&b,a); + r.x1=b; + readsbits(&b,a); + r.x2=b; + readsbits(&b,a); + r.y1=b; + readsbits(&b,a); + r.y2=b; + return r; +} + + +void writeRECT(u8**pos, struct RECT*r) +{ + struct writer_t w; + int t=0; + writer_init(&w, *pos, 256); + writer_writebits(&w, 31, 5); //FIXME:count + writer_writebits(&w, r->x1, 31); + writer_writebits(&w, r->x2, 31); + writer_writebits(&w, r->y1, 31); + writer_writebits(&w, r->y2, 31); + writer_resetbits(&w); + *pos = writer_getpos(&w); +} + +struct CXFORM readCXFORM() +{ + struct CXFORM c; + int bits; + c.hasadd=readbit(); + c.hasmult=readbit(); + bits=getbits(4); + c.alpha = 0; + + if (c.hasmult) + { + c.rmult=getsbits(bits)/65536.0; + c.gmult=getsbits(bits)/65536.0; + c.bmult=getsbits(bits)/65536.0; + if(c.alpha) + c.amult=getsbits(bits)/65536.0; + } + if (c.hasadd) + { + c.radd=getsbits(bits)/65536.0; + c.gadd=getsbits(bits)/65536.0; + c.badd=getsbits(bits)/65536.0; + if(c.alpha) + c.aadd=getsbits(bits)/65536.0; + } + return c; +} + +void CXFORM_write(struct CXFORM *obj, struct writer_t*w) +{ + int bits = 15; + writer_writebit(w,obj->hasadd); + writer_writebit(w,obj->hasmult); + writer_writebits(w, bits, 4); + if (obj->hasmult) + { + writer_writebits(w, obj->rmult, bits); + writer_writebits(w, obj->gmult, bits); + writer_writebits(w, obj->bmult, bits); + if(obj->alpha) + writer_writebits(w, obj->amult, 4); + } + if (obj->hasadd) + { + writer_writebits(w, obj->radd, bits); + writer_writebits(w, obj->gadd, bits); + writer_writebits(w, obj->badd, bits); + if(obj->alpha) + writer_writebits(w, obj->aadd, 4); + } +} + +unsigned char* readSTRING() +{ + unsigned char*now = getinputpos(); + char a; + do + { + input1(&a); + } + while(a); + return now; +} +void MATRIX_init(struct MATRIX*m) +{ + m->hasrotate = 0; + m->hasscale = 0; + m->b[0] = 0; + m->b[1] = 0; + m->a[0][0] = 1; + m->a[1][1] = 1; + m->a[1][0] = 0; + m->a[0][1] = 0; +} +struct MATRIX readMATRIX() +{ + struct MATRIX m; + u8 hasrotate; + u8 translatebits; + u32 translatex; + u32 translatey; + + m.a[0][0] = m.a[1][1] = 1; + m.a[0][1] = m.a[1][0] = 0; + m.hasscale=readbit(); + if(m.hasscale) + { + u8 scalebits=getbits(5); + s32 scalex=getsbits(scalebits); + s32 scaley=getsbits(scalebits); + m.a[0][0]=scalex/65536.0; + m.a[1][1]=scaley/65536.0; + } + m.hasrotate=readbit(); + if(m.hasrotate) + { + u8 rotbits=getbits(5); + s32 rotateskew0=getsbits(rotbits); + s32 rotateskew1=getsbits(rotbits); + m.a[0][1]=rotateskew0/65536.0; + m.a[1][0]=rotateskew1/65536.0; + } + + translatebits=getbits(5); + translatex=getsbits(translatebits); + translatey=getsbits(translatebits); + m.b[0]=translatex; + m.b[1]=translatey; + + return m; +} + +void MATRIX_write(struct MATRIX * m , struct writer_t*w) +{ + writer_writebit (w, m->hasscale); + if(m->hasscale) + { + int bits = 31; + writer_writebits(w, bits, 5); + writer_writebits(w, (u32)(m->a[0][0]*65536.0), bits); + writer_writebits(w, (u32)(m->a[1][1]*65536.0), bits); + } + writer_writebit (w, m->hasrotate); + if(m->hasrotate) + { + int bits = 31; + writer_writebits(w, bits, 5); + writer_writebits(w, (u32)(m->a[0][1]*65536.0), bits); + writer_writebits(w, (u32)(m->a[1][0]*65536.0), bits); + } + + //translate + { + int bits = 31; + writer_writebits(w, bits, 5); + writer_writebits(w, (u32)(m->b[0]), bits); + writer_writebits(w, (u32)(m->b[1]), bits); + } +} + + +int swf_read_tag(struct swf_tag* swftag) +{ + u8*pos2,*pos = getinputpos(); + u16 tag; + u32 taglength; + u32 tagid; + int t; + + input2(&tag); + + taglength = tag & 0x3f; + if (taglength == 0x3f) + { + input4(&taglength); + } + + swftag->id=tag>>6; + swftag->length = taglength; + swftag->data = getinputpos(); + skip(taglength); + pos2 = getinputpos(); + swftag->fulllength = pos2 - pos; + swftag->fulldata = pos; + return 1; +} + +int swf_count_tags() +{ + u8*pos = getinputpos(); + int t=0; + struct swf_tag tag; + + while(1) + { + swf_read_tag(&tag); + t++; + if (tag.id == 0) + break; + } + + setinputpos(pos); + return t; +} + +void placeobject_init (struct PlaceObject*obj, struct swf_tag*tag) +{ + reader_init (tag->data, tag->length); + obj -> id = readu16(); + obj -> depth = readu16(); + obj -> matrix = readMATRIX(); + obj -> hascxform = (getinputpos() < &tag->data[tag->length]); + if(obj -> hascxform) + obj -> cxform = readCXFORM(); +} + +void placeobject_write (struct PlaceObject*obj, struct writer_t*w) +{ + u16 taghead = 0x3f | TAGID_PLACEOBJECT<<6; + u8*pos; + u8*lenpos; + writer_resetbits(w); + writer_write(w, &taghead, 2); + lenpos = writer_getpos(w); + + writer_write(w, &taghead, 2); + writer_write(w, &taghead, 2); + + pos = writer_getpos(w); + + writer_write(w, &obj->id, 2); + writer_write(w, &obj->depth, 2); + MATRIX_write(&obj->matrix, w); + + if(obj->hascxform) + { + CXFORM_write(&obj->cxform, w); + } + writer_resetbits(w); + + *(u32*)lenpos = (u8*)writer_getpos(w) - pos; +} + +void placeobject2_init (struct PlaceObject2*obj,struct swf_tag*tag) +{ + u8 b; + reader_init (tag->data, tag->length); + b=readu8(); + obj->reserved= (b>>7)&1; + obj->hasclipactions= (b>>6)&1; + obj->hasname= (b>>5)&1; + obj->hasratio= (b>>4)&1; + obj->hascolortransform=(b>>3)&1; + obj->hasmatrix= (b>>2)&1; + obj->hascharacter= (b>>1)&1; + obj->hasmove= (b>>0)&1; + + obj->depth = readu16(); + obj->id = -1; + if(obj->hascharacter) { + obj->id = readu16(); + } + if(obj->hasmatrix) { + obj->matrix = readMATRIX(); + } + if(obj->hascolortransform) { + obj->cxform = readCXFORM(); + } + if(obj->hasratio) { + obj->ratio=readu16(); + } + obj->name = 0; + if(obj->hasname) { + obj->name=readSTRING(); + } + if(obj->hasclipactions) { + obj->clipactions=readu16(); + } +} + +void placeobject2_write (struct PlaceObject2*obj, struct writer_t*w) +{ + u8 flags = obj->reserved<<7 | obj->hasclipactions<<6 | obj->hasname<<5 | obj->hasratio<<4 | + obj->hascolortransform<<3 | obj->hasmatrix<<2 | obj->hascharacter<<1 | obj->hasmove; + u16 taghead = 0x3f | TAGID_PLACEOBJECT2<<6; + u8*pos; + u8*lenpos; + writer_resetbits(w); + writer_write(w, &taghead, 2); + lenpos = writer_getpos(w); + writer_write(w, &taghead, 2); + writer_write(w, &taghead, 2); + + pos = writer_getpos(w); + + writer_writeu8(w, flags); + writer_writeu16(w, obj->depth); + if(obj->hascharacter) + writer_writeu16(w, obj->id); + if(obj->hasmatrix) + MATRIX_write(&obj->matrix, w); + if(obj->hascolortransform) + CXFORM_write(&obj->cxform, w); + if(obj->hasratio) + writer_writeu16(w, obj->ratio); + writer_resetbits(w); + if(obj->hasname) + writer_write(w, obj->name, strlen(obj->name) + 1); + if(obj->hasclipactions) + writer_writeu16(w, obj->clipactions); + writer_resetbits(w); + *(u32*)lenpos = (u8*)writer_getpos(w) - pos; +} + +void read_swf(struct swffile*swf, uchar*data, int length) +{ + int pos; + struct flash_header head; + int tagnum; + swf_init(data, length); + head = swf_read_header(data); + logf("<debug> [HEADER] the version is %d", head.version); + logf("<debug> [HEADER] the length is %d", head.length); + logf("<debug> [HEADER] the boundingBox is %d:%d:%d:%d", + head.boundingBox.x1,head.boundingBox.y1, + head.boundingBox.x2,head.boundingBox.y2); + logf("<debug> [HEADER] the rate (frames/second) is %d", head.rate); + logf("<debug> [HEADER] the count (frame number) is %d", head.count); + + tagnum = swf_count_tags(); + swf->tags = (struct swf_tag*)malloc(sizeof(struct swf_tag)*tagnum); + + logf("<debug> [HEADER] the file consists of %d tags", tagnum); + + pos = 0; + while(1) + { + struct swf_tag tag; + swf_read_tag(&tag); + logf("<debug> read tag %02x (%d bytes)", tag.id, tag.length); + swf->tags[pos] = tag; + pos++; + if(tag.id == TAGID_END) + break; + } + swf->tagnum = tagnum; + swf->header = head; +} + +int definingtagids[] = +{TAGID_DEFINESHAPE, + TAGID_DEFINESHAPE2, + TAGID_DEFINESHAPE3, + TAGID_DEFINEMORPHSHAPE, + TAGID_DEFINEFONT, + TAGID_DEFINEFONT2, + TAGID_DEFINETEXT, + TAGID_DEFINETEXT2, + TAGID_DEFINEEDITTEXT, + TAGID_DEFINEBITS, + TAGID_DEFINEBITSJPEG2, + TAGID_DEFINEBITSJPEG3, + TAGID_DEFINEBITSLOSSLESS, + TAGID_DEFINEBITSLOSSLESS2, + TAGID_DEFINEMOVIE, + TAGID_DEFINESPRITE, + TAGID_DEFINEBUTTON, + TAGID_DEFINEBUTTON2, + TAGID_DEFINESOUND, + -1 +}; + +// tags which may be used inside a sprite definition +int spritetagids[] = +{TAGID_SHOWFRAME, + TAGID_PLACEOBJECT, + TAGID_PLACEOBJECT2, + TAGID_REMOVEOBJECT, + TAGID_REMOVEOBJECT2, //? + TAGID_DOACTION, + TAGID_STARTSOUND, + TAGID_FRAMELABEL, + TAGID_SOUNDSTREAMHEAD, + TAGID_SOUNDSTREAMHEAD2, + TAGID_SOUNDSTREAMBLOCK, + TAGID_END, + -1 +}; + +int getidfromtag(struct swf_tag* tag) +{ + // todo: check for more than one id + return *(u16*)tag->data; +} + +void setidintag(struct swf_tag* tag, int id) +{ + *(u16*)tag->data = id; +} + +char is_sprite_tag (int id) +{ + + int t=0; + while(spritetagids[t]>=0) + { + if(spritetagids[t] == id) + return 1; + t++; + } + return 0; +} + +char is_defining_tag (int id) +{ + + int t=0; + while(definingtagids[t]>=0) + { + if(definingtagids[t] == id) + return 1; + t++; + } + return 0; +} + +struct swf_tag* duptag(struct swf_tag*tag) +{ + struct swf_tag* newtag = (struct swf_tag*)malloc(sizeof(struct swf_tag)); + newtag->id = tag->id; + newtag->fulldata = (u8*)malloc(tag->fulllength); + newtag->fulllength = tag->fulllength; + newtag->data = newtag->fulldata + (tag->data - tag->fulldata); + newtag->length = tag->length; + memcpy(newtag->fulldata, tag->fulldata, tag->fulllength); + return newtag; +} + diff --git a/src/flash.h b/src/flash.h new file mode 100644 index 00000000..255aeff5 --- /dev/null +++ b/src/flash.h @@ -0,0 +1,196 @@ +/* flash.h + Header file for flash.c + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#ifndef __flash_h__ +#define __flash_h__ + +#include "types.h" + +#define TAGID_END 0 +#define TAGID_SHOWFRAME 1 +#define TAGID_DEFINESHAPE 2 +#define TAGID_PLACEOBJECT 4 +#define TAGID_REMOVEOBJECT 5 +#define TAGID_DEFINEBITS 6 +#define TAGID_DEFINEBUTTON 7 +#define TAGID_JPEGTABLES 8 +#define TAGID_BACKGROUNDCOLOR 9 +#define TAGID_DEFINEFONT 10 +#define TAGID_DEFINETEXT 11 +#define TAGID_DOACTION 12 +#define TAGID_DEFINEFONTINFO 13 +#define TAGID_DEFINESOUND 14 +#define TAGID_STARTSOUND 15 +#define TAGID_SOUNDSTREAMHEAD 18 +#define TAGID_SOUNDSTREAMHEAD2 18 +#define TAGID_SOUNDSTREAMBLOCK 19 +#define TAGID_DEFINEBITSLOSSLESS 20 +#define TAGID_DEFINEBITSJPEG2 21 +#define TAGID_DEFINESHAPE2 22 +#define TAGID_PROTECT 24 +#define TAGID_PLACEOBJECT2 26 +#define TAGID_REMOVEOBJECT2 28 +#define TAGID_DEFINESHAPE3 32 +#define TAGID_DEFINETEXT2 33 +#define TAGID_DEFINEBUTTON2 34 +#define TAGID_DEFINEBITSJPEG3 35 +#define TAGID_DEFINEBITSLOSSLESS2 36 +#define TAGID_DEFINEEDITTEXT 37 +#define TAGID_DEFINEMOVIE 38 +#define TAGID_DEFINESPRITE 39 +#define TAGID_FRAMELABEL 43 +#define TAGID_DEFINEMORPHSHAPE 46 +#define TAGID_DEFINEFONT2 48 +#define TAGID_EXPORTASSETS 56 +#define TAGID_IMPORTASSETS 57 +#define TAGID_ENABLEDEBUGGER 58 + +#include "bitio.h" + +struct swf_tag; +struct RECT; +struct RGB; +struct MATRIX; +struct CXFORM; +struct CLIPACTIONS; + +struct swf_tag +{ + u8 id; + u32 length; + u8*data; + u32 fulllength; // includes id + u8*fulldata; // likewise +}; + +struct RGB +{ + byte r,g,b; +}; + +struct RGBA +{ + byte r,g,b,a; +}; + +struct RECT +{ + int x1, y1, x2, y2; +}; + +struct MATRIX +{ + u8 hasscale; + u8 hasrotate; + float a[2][2]; + int b[2]; +}; + +struct CXFORM +{ + u8 hasadd; + u8 hasmult; + float rmult, gmult, bmult, amult; + float radd, gadd, badd, aadd; + u8 alpha; +}; + +struct GRADIENT +{ + int num; + u8 ratios[8]; + struct RGB rgb[8]; + struct RGBA rgba[8]; +}; + +struct RECT readRECT(); +struct RGB readRGB(); +struct MATRIX readMATRIX(); +unsigned char* readSTRING(); +struct CXFORM readCXFORM(); +struct CLIPACTIONS readCLIPACTIONS(); + +void writeRECT(u8**pos, struct RECT*r); + +void swf_init(uchar*newdata, int newlength); +struct flash_header +{ + int version; + u32 length; + struct RECT boundingBox; + u16 rate; + u16 count; + + u8*headerdata; + int headerlength; +}; + +struct swffile +{ + struct flash_header header; + int tagnum; + struct swf_tag* tags; +}; + +struct flash_header swf_read_header(); +struct RGB readRGB(); +struct RGBA readRGBA(); +struct GRADIENT readGRADIENT(int shape); +struct RECT readRECT(); +struct CXFORM readCXFORM(); +struct MATRIX readMATRIX(); +unsigned char* readSTRING(); +int swf_read_tag(struct swf_tag* swftag); +int swf_count_tags(); + + +struct PlaceObject +{ + u16 id; + u16 depth; + struct MATRIX matrix; + struct CXFORM cxform; + u8 hascxform; +}; + +struct PlaceObject2 +{ + u8 reserved; + u8 hasclipactions; + u8 hasname; + u8 hasratio; + u8 hascolortransform; + u8 hasmatrix; + u8 hascharacter; + u8 hasmove; + + u16 depth; + int id; + struct MATRIX matrix; + struct CXFORM cxform; + u16 ratio; + char * name; + u16 clipactions; +}; + + +void placeobject_init (struct PlaceObject*obj, struct swf_tag*tag); +void placeobject_write (struct PlaceObject*obj, struct writer_t*w); + +void placeobject2_init (struct PlaceObject2*obj, struct swf_tag*tag); + +void read_swf(struct swffile*swf, uchar*data, int length); + +int getidfromtag(struct swf_tag* tag); +void setidintag(struct swf_tag* tag, int id); +char is_sprite_tag (int id); +char is_defining_tag (int id); +struct swf_tag* duptag(struct swf_tag*tag); + +#endif //__flash_h__ diff --git a/src/reloc.c b/src/reloc.c new file mode 100644 index 00000000..2f82afa5 --- /dev/null +++ b/src/reloc.c @@ -0,0 +1,285 @@ +/* reloc.h + Implements swf_relocate(), which changes the id range of a swf file in + memory. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#include "flash.h" + +static struct swffile file; + +int slaveids[65536]; + + +void map_ids_mem(u8*mem, int length); +static struct swf_tag* map_ids(struct swf_tag*tag) +{ + map_ids_mem(tag->fulldata, tag->fulllength); + return tag; +} + +void maponeid(void*idpos) +{ + u16*idptr = (u16*)idpos; + if(slaveids[*idptr]<0) { + logf("<error> Trying to map id never encountered before: id=%d", *idptr); + return ; + } + logf("<debug> mapping %d to %d", *idptr, slaveids[*idptr]); + *idptr = slaveids[*idptr]; +} + + +// take a memory region which contains a tag, and +// map the ids inside this tag to new values +void map_ids_mem(u8*mem, int length) +{ + int num=1; + struct swf_tag newtag_instance; + struct swf_tag*newtag = &newtag_instance; + reader_init (mem, length); + swf_read_tag(newtag); + + switch(newtag->id) + { + case TAGID_PLACEOBJECT: + maponeid(&newtag->data[0]); + break; + case TAGID_PLACEOBJECT2: + // only if placeflaghascharacter + if(!(newtag->data[0]&2)) + break; + maponeid(&newtag->data[3]); + break; + case TAGID_REMOVEOBJECT: + maponeid(&newtag->data[0]); + break; + case TAGID_STARTSOUND: + maponeid(&newtag->data[0]); + break; + case TAGID_DEFINESPRITE: { + u8*mem = &newtag->data[4]; + int len = newtag->length-4; + + while(1) { + u8*fmem = mem; + int flen = len; + struct swf_tag sprtag; + + reader_init (mem, len); + swf_read_tag (&sprtag); + + mem = getinputpos(); + len = getinputlength(); + + if(sprtag.id == TAGID_END) + break; + + map_ids_mem (fmem,flen); + } + } + break; + case TAGID_DEFINEBUTTON2: // has some font ids in the button records + num++; + //fallthrough + case TAGID_DEFINEBUTTON: + reader_init (newtag->data, newtag->length); + readu16(); //button id + if(num>1) + { + readu8(); //flag + readu16(); //offset + } + while(1) + { + u16 charid; + if(!readu8()) //flags + break; + charid = *(u16*)getinputpos(); + maponeid(getinputpos()); + readu16(); //char + readu16(); //layer + readMATRIX(); + readCXFORM(); + } + // ... + break; + case TAGID_DEFINEEDITTEXT: { + u8 flags1,flags2; + reader_init (newtag->data, newtag->length); + readu16(); //id + readRECT(); //bounding box + resetbits(); + flags1 = readu8(); + flags2 = readu8(); + if(flags1 & 128) + maponeid(getinputpos()); + } + break; + case TAGID_DEFINETEXT2: + num ++; + case TAGID_DEFINETEXT: { + int glyphbits, advancebits; + reader_init (newtag->data, newtag->length); + readu16(); //id + readRECT(); //bounding box + readMATRIX(); //matrix + resetbits(); + glyphbits = readu8(); //glyphbits + advancebits = readu8(); //advancebits + while(1) { + u16 flags = getbits(8); + printf("define text flags: %02x\n", flags); + if(!flags) break; + if(flags & 128) // text style record + { + if(flags & 8) { // hasfont + maponeid(getinputpos()); + resetbits(); + readu16(); + } + if(flags & 4) { // hascolor + if(num==1) readRGB(); + else readRGBA(); + } + if(flags & 2) { //has x offset + resetbits(); + readu16(); + } + if(flags & 1) { //has y offset + resetbits(); + readu16(); + } + if(flags & 8) { //has height + resetbits(); + readu16(); + } + } else { // glyph record + getbits(glyphbits); + getbits(advancebits); + break; + } + } + break; + } + case TAGID_DEFINEFONTINFO: + maponeid(&newtag->data[0]); + break; + + case TAGID_DEFINESHAPE3: // these thingies might have bitmap ids in their fillstyles + num++; //fallthrough + case TAGID_DEFINESHAPE2: + num++; //fallthrough + case TAGID_DEFINESHAPE: { + u16 count; + int t; + struct RECT r; + reader_init (newtag->data, newtag->length); + readu16(); // id; + r = readRECT(); // bounds +// printf("%d shape bounds: %d %d %d %d\n",newtag->id,r.x1,r.y1,r.x2,r.y2); + resetbits(); + count = readu8(); + if(count == 0xff && num>1) + count = readu16(); +// printf("%d fillstyles\n", count); + for(t=0;t<count;t++) + { + int type; + u8*pos; + pos=getinputpos(); +// printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", +// pos[0],pos[1],pos[2],pos[3],pos[4],pos[5],pos[6],pos[7]); + type = readu8(); //type +// printf("fillstyle %d is type 0x%02x\n", t, type); + if(type == 0) { + if(num == 3) + readRGBA(); + else + readRGB(); + } + if(type == 0x10 || type == 0x12) + { + readMATRIX(); + resetbits(); + readGRADIENT(num); + } + if(type == 0x40 || type == 0x41) + { + resetbits(); + // we made it. + if(*(u16*)getinputpos() != 65535) + maponeid(getinputpos()); + + readu16(); + readMATRIX(); + } + //... + } + } + break; + default: + break; + } +} + +static int*bitmap; + +static int get_free_id() +{ + int t; + for (t=1;t<65536;t++) + { + if(bitmap[t] == -1) + { + bitmap[t] = 1; + return t; + } + } + return -1; +} + +void swf_relocate (u8*data, int length, int*_bitmap) +{ + int pos; + bitmap = _bitmap; + read_swf(&file, data, length); + memset(slaveids, -1, sizeof(slaveids)); + + pos = 0; + while(file.tags[pos].id != 0) { + struct swf_tag*tag = &file.tags[pos]; + + map_ids(&file.tags[pos]); + + if(is_defining_tag(tag->id)) + { + int newid; + int id; + + id = getidfromtag(tag); //own id + + if(bitmap[id] < 0) { //free + newid = id; + } + else { + newid = get_free_id(id); + } + bitmap[newid] = 1; + slaveids[id] = newid; + + logf("<debug> sprite id %d mapped to %d",id, newid); + + setidintag(tag, newid); + + logf("<debug> [sprite defs] write tag %02x (%d bytes in body)", + tag->id, tag->length); + } + pos++; + } +} + diff --git a/src/reloc.h b/src/reloc.h new file mode 100644 index 00000000..8624c440 --- /dev/null +++ b/src/reloc.h @@ -0,0 +1,14 @@ +/* reloc.h + Header file for reloc.c + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#ifndef __swf_reallocate__ +#define __swf_reallocate__ +void swf_relocate (u8*data, int length, int*bitmap); +#endif // __swf_reallocate__ + diff --git a/src/settings.h b/src/settings.h new file mode 100644 index 00000000..da73a716 --- /dev/null +++ b/src/settings.h @@ -0,0 +1,26 @@ +/* args.h + Settings for swfcombine. This is deliberately not named "config.h" to + avoid conflicts with GNU autoconf. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#ifndef __config_h__ +#define __config_h__ +struct config_t +{ + char overlay; + char alloctest; + char clip; + char stack; + int loglevel; + int movex; + int movey; + float scalex; + float scaley; +}; +extern struct config_t config; +#endif diff --git a/src/swfcombine.1 b/src/swfcombine.1 new file mode 100644 index 00000000..d1e484e2 --- /dev/null +++ b/src/swfcombine.1 @@ -0,0 +1,83 @@ +.TH swfcombine "1" "October 2001" "swfcombine" "swftools" +.SH NAME +swfcombine - a tool for combining swf (flash) files +.SH Synopsis +.B swfcombine +[\fIoptions\fR] [\fImasterfile.swf\fR] [\fIslavename1=\fR][\fIslavefile1.swf\fR] ... [\fIslavenameN=\fR][\fIslavefileN.swf\fR] +.SH DESCRIPTION +Take two or more SWF files, and combine them into a new SWF. SWFs can either +be stacked (no masterfile is present) or inserted (into the masterfile). +.PP +SWF files are animation files which can be displayed in Web Browsers using +the Flash Plugin. +.LP +For template mechanisms, it's often convenient to separate the processes +of generating small animation fragments, and merging them all into a big +movie. swfcombine can be used to perform the latter. +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print short help message and exit +.\".TP +.\" \fB\-\-version\fR +.\" Print version info and exit +.TP +\fB\-o\fR, \fB\-\-output\fR \fIfilename\fR +Explicitly specify output file. (otherwise, output.swf will be used) +.TP +\fB\-l\fR, \fB\-\-overlay\fR +Don't remove any master objects, only overlay new objects. +.TP +\fB\-c\fR, \fB\-\-clip\fR +Clip the slave objects by the corresponding master objects. +.TP +\fB\-v\fR, \fB\-\-verbose\fR +Be verbose. Use more than one -v for greater effect. +.TP +\fB\-t\fR, \fB\-\-stack\fR +Don't assume the first file is a master file. Instead, store each +file in a seperate frame. +.TP +\fB\-x\fR, \fB\-\-xpos\fR \fIxpos\fR +(move x) Adjust position of slave by xpos twips (1/20 pixel). +.TP +\fB\-y\fR, \fB\-\-ypos\fR \fIypos\fR +(move y) Adjust position of slave by ypos twips (1/20 pixel). +.TP +\fB\-s\fR, \fB\-\-scale\fR \fIscale\fR +(scale) Adjust size of slave by scale% +.PP +.SH Combining two or more .swf files using a master file +Of the flash files to be combined, all except one will be packed into a sprite +structure (Movieclip) which will then be inserted into the master .swf file. +This means that, in terms of trees, when combining several flash files, +one will form the root of the tree, while the others will be +appended to the root as a subnode. +The user has to specify which of the files will become the root +of the tree ("master") and which will be the appended nodes ("slaves"). +The slave files must all have a name, which is then used to determine +their exact position inside the master file. +The slave files will then be converted into sprites, inserted into the +master file, and all PlaceObject tags in the master file which match the +name of the slave file will be updated to correctly display the slave sprite. +.SH Combining (stacking) one or more .swf files without a master +The flash files will be inserted in seperate frames. They will still be +packed into Movieclips, therefore the outputfile will have exactly as many +frames as there were inputfiles. Also, the files don't need to have names. +If you want to access the Movieclips, their names are frameXX, where XX is +the decimal number of the file, starting by zero (00). + +.SH EXAMPLES + +Create two flash movies. Insert some rectangle into one of them, and give +it a name. (E.g. "foo") Now call + +swfcombine -o combined.swf master.swf foo:slave.swf + +As a result, the slave movie should be visible inside the master movie +at the position where the rectangle used to be. + +.SH AUTHOR + +Matthias Kramm <kramm@quiss.org> + diff --git a/src/swfcombine.c b/src/swfcombine.c new file mode 100644 index 00000000..77597b66 --- /dev/null +++ b/src/swfcombine.c @@ -0,0 +1,431 @@ +/* swfcombine.c + main routine for swfcombine(1), which is a tool for merging .swf-files. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "args.h" +#include "combine.h" +#include "settings.h" +#include "types.h" +#include "flash.h" + +char * master_filename = 0; +char * master_name = 0; +char * slave_filename[128]; +char * slave_name[128]; +int slave_movex[128]; +int slave_movey[128]; +float slave_scalex[128]; +float slave_scaley[128]; +int numslaves = 0; + +char * outputname = "output.swf"; + +int args_callback_option(char*name,char*val) { + if(!strcmp(name,"c")) + { + config.clip = 1; + return 0; + } + else if(!strcmp(name,"l")) + { + config.overlay = 1; + return 0; + } + else if (!strcmp(name, "o")) + { + outputname = val; + return 1; + } + else if (!strcmp(name, "v")) + { + config.loglevel ++; + return 0; + } + else if (!strcmp(name, "a")) + { + config.alloctest = 1; + return 0; + } + else if (!strcmp(name, "x")) + { + config.movex = atoi(val); + return 1; + } + else if (!strcmp(name, "y")) + { + config.movey = atoi(val); + return 1; + } + else if (!strcmp(name, "s")) + { + config.scalex = config.scaley = atoi(val)/100.0; + return 1; + } + else if (!strcmp(name, "t")) + { + if(master_filename) { + fprintf(stderr, "error with arguments. Try --help.\n"); + exit(1); + } + config.stack = 1; + master_filename = "__none__"; + return 0; + } + else if (!strcmp(name, "V")) + { + printf("swfcombine - part of swftools 0.0.1\n"); + exit(0); + } + else + { + fprintf(stderr, "Unknown option: -%s\n", name); + exit(1); + } +} + +struct options_t +{ + char*shortoption; + char*longoption; +} options[] = +{{"o","output"}, + {"s","scale"}, + {"x","xpos"}, + {"y","ypos"}, + {"l","overlay"}, + {"v","verbose"}, + {"V","version"}, + {"c","clip"}, +}; + +int args_callback_longoption(char*name,char*val) { + int t; + for(t=0;t<sizeof(options)/sizeof(struct options_t);t++) + if(!strcmp(options[t].longoption, name)) + return args_callback_option(options[t].shortoption,val); + fprintf(stderr, "Unknown option: --%s\n", name); + exit(1); +} + +int args_callback_command(char*name, char*val) { + char*myname = strdup(name); + char*filename; + filename = strchr(myname, '='); + if(filename) { + *filename = 0; + filename++; + } else { + // argument has no explicit name field. guess one from the file name + char*path = strrchr(myname, '/'); + char*ext = strrchr(myname, '.'); + if(!path) path = myname; + else path ++; + if(ext) *ext = 0; + myname = path; + filename = name; + } + + if(!master_filename) { + + master_filename = filename; + master_name = myname; + } else { + logf("<verbose> slave entity %s (named \"%s\")\n", filename, myname); + + slave_filename[numslaves] = filename; + slave_name[numslaves] = myname; + slave_movex[numslaves] = config.movex; + slave_movey[numslaves] = config.movey; + slave_scalex[numslaves] = config.scalex; + slave_scaley[numslaves] = config.scaley; + config.movex = config.movey = 0; + config.scalex = config.scaley = 1.0; + numslaves ++; + } + return 0; +} + +void args_callback_usage(char*name) +{ + printf("Usage: %s [-l] [-o outputfile] [name=]masterfile [-x xpos] [-y ypos] [-s scale] [name1=]slavefile1 .. [-x xpos] [-y ypos] [-s scale] [nameN=]slavefileN\n", name); + printf("\n"); + printf("-o outputfile explicitly specify output file. (otherwise, output.swf will be used)\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("-x xpos (move x) Adjust position of slave by xpos twips (1/20 pixel)\n"); + printf("-y ypos (move y) Adjust position of slave by ypos twips (1/20 pixel)\n"); + printf("-s scale (scale) Adjust size of slave by scale%\n"); + printf("\n"); +} + +/* read a whole file in memory */ +char* fi_slurp(FILE*fi, unsigned int * setlength) +{ + char * mem; + long long int length; //;) + long long int pos = 0; + fseek(fi,0,SEEK_END); + length = ftell(fi); + fseek(fi,0,SEEK_SET); + if(!length) + return 0; + mem = malloc(length); + if(!mem) + return 0; + while(!feof(fi)) + { + pos += fread(&mem[pos], 1, 65536, fi); + } + if (setlength) + *setlength = length; + return mem; +} + +void fi_dump(FILE*fi, void*_mem, int length) +{ + char*mem = (char*)_mem; + int pos = 0; + while(pos < length) + { + int size = 65536; + if (size > (length - pos)) + size = (length - pos); + pos += fwrite(&mem[pos], 1, size, fi); + } +} + +void makestackmaster(u8**masterdata, int*masterlength) +{ + u8 head[] = {'F','W','S'}; + u8 *pos; + u32 * fixpos; + int t; + struct RECT box; + int strlength = 0; + int fileversion = 1; + + logf("<error> stacking doesn't work yet. Prepare for problems."); + + /* scan all slaves for bounding box */ + for(t=0;t<numslaves;t++) + { + FILE*fi=fopen(slave_filename[t],"rb"); + u8 data[256]; + int ret; + struct flash_header head; + strlength += strlen(slave_name[t]) + 9; + if(!fi) { + logf("<fatal> Couldn't open %s.", slave_filename[t]); + exit(1); + } + ret = fread(data,1,256,fi); + if(ret < 13) { + logf("<fatal> File %s is to small (%d bytes)", slave_filename[t], ret); + exit(1); + } + swf_init(data,256); + head = swf_read_header(); + logf("<verbose> File %s has bounding box %d:%d:%d:%d\n", + slave_filename[t], + head.boundingBox.x1, head.boundingBox.y1, + head.boundingBox.x2, head.boundingBox.y2); + if(head.version > fileversion) + fileversion = head.version; + if(!t) + box = head.boundingBox; + else { + if(head.boundingBox.x1 < box.x1) + box.x1 = head.boundingBox.x1; + if(head.boundingBox.y1 < box.y1) + box.y1 = head.boundingBox.y1; + if(head.boundingBox.x2 > box.x2) + box.x2 = head.boundingBox.x2; + if(head.boundingBox.y2 > box.y2) + box.y2 = head.boundingBox.y2; + } + logf("<verbose> New master bounding box is %d:%d:%d:%d\n", + box.x1, box.y1, + box.x2, box.y2); + fclose(fi); + } + + /* we don't have a master, so we create one ourselves. */ + /* (please notice the philosophical content) */ + *masterlength = (numslaves + 1) * 32 + strlength; + *masterdata = (u8*)malloc(*masterlength); + pos = *masterdata; + memcpy(pos, head, sizeof(head)); + pos += sizeof(head); + *pos++ = fileversion; + fixpos = (u32*)pos; + *(u32*)pos = 0x12345678; // to be overwritten + pos += 4; + writeRECT(&pos, &box); + *(u16*)pos = 0x2000; // framerate + pos += 2; + *(u16*)pos = numslaves; + pos += 2; + for(t=0;t<numslaves;t++) + { + char buf[128]; + int namelen; + + if(1) { + sprintf(buf, "Frame%02d", t); + slave_name[t] = strdup(buf); + } + namelen = strlen(slave_name[t]); + + *(u16*)&pos[0] = (u16)(TAGID_DEFINESPRITE<<6) + 6; + *(u16*)&pos[2] = t+1; //ID + *(u16*)&pos[4] = 0; // Frames + *(u16*)&pos[6] = 0; // TAG1 + *(u16*)&pos[8] = (u16)(TAGID_PLACEOBJECT2<<6) + 6 + namelen; + *(u16*)&pos[10]= 34; //flags: id+name + *(u16*)&pos[11]= 1; // depth + *(u16*)&pos[13]= t+1; // id + sprintf(&pos[15],slave_name[t]); + pos += 15 + namelen + 1; + *(u16*)&pos[0]= (u16)(TAGID_SHOWFRAME<<6) + 0; + pos += 2; + if(t!=numslaves-1) + { + *(u16*)&pos[0]= (u16)(TAGID_REMOVEOBJECT2<<6) + 2; + *(u16*)&pos[2]= 1; // depth; + pos += 4; + } + } + *(u16*)pos = TAGID_END<<6 + 0; + *masterlength = pos - *masterdata; + *fixpos = *masterlength; +} + +struct config_t config; +int main(int argn, char *argv[]) +{ + FILE*fi; + u8*masterdata; + unsigned int masterlength; + u8*slavedata; + unsigned int slavelength; + u8*newdata; + unsigned int newlength; + int t; + + config.overlay = 0; + config.alloctest = 0; + config.clip = 0; + config.loglevel = 2; + config.movex = 0; + config.movey = 0; + config.scalex = 1.0; + config.scaley = 1.0; + config.stack = 0; + + processargs(argn, argv); + initLog(0,-1,0,0,-1,config.loglevel); + + if(config.stack) { + + if(config.overlay) { + logf("<error> Can't combine -l and -t"); + exit(1); + } + if(config.clip) { + logf("<error> Can't combine -c and -t"); + exit(1); + } + logf("<verbose> (stacking) %d files found\n", numslaves); + + makestackmaster(&masterdata,&masterlength); + + logf("<verbose> Generated %d bytes of master data", masterlength); + } + else { + logf("<verbose> master entity %s (named \"%s\")\n", master_filename, master_name); + fi = fopen(master_filename, "rb"); + if(!fi) { + fprintf(stderr, "Failed to open %s\n", master_filename); + return 1; + } + masterdata = fi_slurp(fi, &masterlength); + if(!masterdata) { + fprintf(stderr, "Failed to read from %s\n", master_filename); + return 1; + } + logf("<debug> Read %d bytes from masterfile\n", masterlength); + fclose(fi); + } + + for(t=0;t<numslaves;t++) + logf("<verbose> slave entity(%d) %s (named \"%s\")\n", t+1, slave_filename[t], slave_name[t]); + + if (config.alloctest) + { + int*bitmap = malloc(sizeof(int)*65536); + memset(bitmap, -1, 65536*sizeof(int)); + memset(bitmap, 1, 101*sizeof(int)); + swf_relocate(masterdata, masterlength, bitmap); + newdata = masterdata; + newlength = masterlength; + free(bitmap); + } + else + { + if (!numslaves) + { + logf("<error> You must have at least one slave entity."); + return 0; + } + for(t = 0; t < numslaves; t++) + { + config.movex = slave_movex[t]; + config.movey = slave_movey[t]; + config.scalex = slave_scalex[t]; + config.scaley = slave_scaley[t]; + + logf("<notice> Combine [%s]%s and [%s]%s", master_name, master_filename, + slave_name[t], slave_filename[t]); + fi = fopen(slave_filename[t], "rb"); + if(!fi) { + fprintf(stderr, "Failed to open %s\n", slave_filename[t]); + return 1; + } + slavedata = fi_slurp(fi, &slavelength); + if(!slavedata) { + fprintf(stderr, "Failed to read from %s\n", slave_filename[t]); + return 1; + } + logf("<debug> Read %d bytes from slavefile\n", slavelength); + fclose(fi); + + newdata = combine(masterdata, masterlength, slave_name[t], slavedata, slavelength, &newlength); + if(!newdata) { + logf("<fatal> Aborting."); + return 1; + } + + free(masterdata); + masterdata = newdata; + masterlength = newlength; + } + } + + logf("<debug> New File is %d bytes \n", newlength); + if(newdata && newlength) { + FILE*fi = fopen(outputname, "wb"); + fi_dump(fi, newdata, newlength); + fclose(fi); + } + return 0; +} + diff --git a/src/swfdump.1 b/src/swfdump.1 new file mode 100644 index 00000000..0918cb16 --- /dev/null +++ b/src/swfdump.1 @@ -0,0 +1,23 @@ +.TH swfdump "1" "October 2001" "swfdump" "swftools" +.SH NAME +swfdump - a tool for displaying information about flash files +.SH Synopsis +.B swfdump +[\fIoptions\fR] [\fIfile.swf\fR] +.SH DESCRIPTION +swfdump shows ids, names and depths of objects defined in the SWF file. +.PP +SWF files are animation files which can be displayed in Web Browsers using +the Flash Plugin. +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print short help message and exit +.\".TP +.\" \fB\-\-version\fR +.\" Print version info and exit + +.SH AUTHOR + +Matthias Kramm <kramm@quiss.org> + diff --git a/src/swfdump.c b/src/swfdump.c new file mode 100644 index 00000000..fc9fda1b --- /dev/null +++ b/src/swfdump.c @@ -0,0 +1,109 @@ +/* swfdump.c
+ Shows the structure of a swf file
+
+ Part of the swftools package.
+
+ Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
+
+ This file is distributed under the GPL, see file COPYING for details */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include "../lib/rfxswf.h"
+#include "args.h"
+
+char * filename = 0;
+
+/* idtab stores the ids which are defined in the file. This allows us
+ to detect errors in the file. (i.e. ids which are defined more than
+ once */
+char idtab[65536];
+
+int args_callback_option(char*name,char*val)
+{
+}
+int args_callback_longoption(char*name,char*val)
+{
+}
+void args_callback_usage(char*name)
+{
+ printf("Usage: %s file.swf\n", name);
+ printf("\n");
+}
+int args_callback_command(char*name,char*val)
+{
+ if(filename) {
+ fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
+ filename, name);
+ }
+ filename = name;
+ return 0;
+}
+
+int main (int argc,char ** argv)
+{
+ SWF swf;
+ TAG*tag;
+ int f;
+ char prefix[128];
+ prefix[0] = 0;
+ memset(idtab,0,65536);
+
+ processargs(argc, argv);
+
+ f = open(filename,O_RDONLY);
+
+ if (f<0)
+ {
+ perror("Couldn't open file: ");
+ exit(1);
+ }
+ if FAILED(ReadSWF(f,&swf))
+ {
+ fprintf(stderr,"%s is not a valid SWF file or contains errors.\n",filename);
+ close(f);
+ exit(1);
+ }
+ close(f);
+
+ tag = swf.FirstTag;
+
+ while(tag) {
+ printf("[%02x] %s%s", tag->id, prefix, getTagName(tag));
+ if(isDefiningTag(tag)) {
+ U16 id = GetDefineID(tag);
+ printf(" defines id %04x", id);
+ if(idtab[id])
+ fprintf(stderr, "Error: Id %04x is defined more than once.\n", id);
+ idtab[id] = 1;
+ }
+ else if(tag->id == ST_PLACEOBJECT ||
+ tag->id == ST_PLACEOBJECT2) {
+ printf(" places id %04x at depth %04x", GetPlaceID(tag), GetDepth(tag));
+ if(GetName(tag))
+ printf(" name \"%s\"",GetName(tag));
+ }
+ else if(tag->id == ST_REMOVEOBJECT) {
+ printf(" removes id %04x from depth %04x", GetPlaceID(tag), GetDepth(tag));
+ }
+ else if(tag->id == ST_REMOVEOBJECT2) {
+ printf(" removes object from depth %04x", GetDepth(tag));
+ }
+
+ printf("\n");
+
+ if(tag->id == ST_DEFINESPRITE)
+ {
+ sprintf(prefix, " ");
+ }
+ if(tag->id == ST_END)
+ {
+ sprintf(prefix, "");
+ }
+ tag = tag->next;
+ }
+
+ FreeTags(&swf);
+ return 0;
+}
+
diff --git a/src/swfstrings.1 b/src/swfstrings.1 new file mode 100644 index 00000000..0ab12a7b --- /dev/null +++ b/src/swfstrings.1 @@ -0,0 +1,24 @@ +.TH swfstrings "1" "October 2001" "swfstrings" "swftools" +.SH NAME +swfstrings - a tool for extracting text out of swf files. +.SH Synopsis +.B swfstrings +[\fIoptions\fR] [\fIfile.swf\fR] +.SH DESCRIPTION +swfstrings extracts text out of DEFINETEXT tags of the .swf file. It also +displays the fonts being used. +.PP +SWF files are animation files which can be displayed in Web Browsers using +the Flash Plugin. +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Print short help message and exit +.\".TP +.\" \fB\-\-version\fR +.\" Print version info and exit + +.SH AUTHOR + +Rainer Böhme <rfxswf@reflex-studio.de> + diff --git a/src/swfstrings.c b/src/swfstrings.c new file mode 100644 index 00000000..2bf1d9a8 --- /dev/null +++ b/src/swfstrings.c @@ -0,0 +1,54 @@ +/* swfstrings.c
+ Scans a swf file for strings
+
+ Part of the swftools package.
+
+ Copyright (c) 2000,2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include "../lib/rfxswf.h"
+
+SWF swf;
+
+void fontcallback(U16 id,U8 * name)
+{ LPSWFFONT font;
+ LPTAG t;
+
+ FontExtract(&swf,id,&font);
+ printf("#< %s %s %s>\n",name,FontIsBold(font)?"bold":"",FontIsItalic(font)?"italic":"");
+
+ t = swf.FirstTag;
+
+ while (t)
+ { TextPrintDefineText(t,font);
+ t = NextTag(t);
+ }
+
+ FontFree(font);
+}
+
+int main (int argc,char ** argv)
+{ int f;
+
+ if (argc>1)
+ { f = open(argv[1],O_RDONLY);
+ if (f>=0)
+ { if FAILED(ReadSWF(f,&swf))
+ { fprintf(stderr,"%s is not a valid SWF file or contains errors.\n",argv[1]);
+ close(f);
+ }
+ else
+ { close(f);
+ FontEnumerate(&swf,&fontcallback);
+ FreeTags(&swf);
+ }
+ } else fprintf(stderr,"File not found: %s\n",argv[1]);
+ }
+ else fprintf(stderr,"\nreflex SWF Text Scan Utility\n(w) 2000 by Rainer Boehme <rb@reflex-studio.de>\n\nUsage: %s filename.swf\n", argv[0]);
+
+ return 0;
+}
+
diff --git a/src/types.h b/src/types.h new file mode 100644 index 00000000..a5b540d7 --- /dev/null +++ b/src/types.h @@ -0,0 +1,33 @@ +/* types.h + Some typedefs to make life simpler. If this file causes you problems, you might + try to remove all #include "types.h" and live with what configure does define. + + Part of the swftools package. + + Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> + + This file is distributed under the GPL, see file COPYING for details */ + +#ifndef __types_h__ +#define __types_h__ +typedef long unsigned w32; +typedef short unsigned w16; +typedef unsigned char u8; +typedef signed char s8; +typedef short unsigned u16; +typedef short signed s16; +typedef long unsigned u32; +typedef long signed s32; +typedef long long unsigned u64; +typedef long long signed s64; +typedef unsigned char byte; +typedef unsigned char uchar; +typedef signed char sbyte; +typedef unsigned short int word; +typedef signed short int sword; +typedef unsigned long int dword; +typedef signed long int sdword; +typedef signed short int integer; +typedef signed long int longint; +typedef long double extended; +#endif // __types_h__ |