removed bit 31 warning, added swf_ReadABCfile
[swftools.git] / lib / rfxswf.c
index ecc5fd3..a09d29c 100644 (file)
@@ -46,6 +46,7 @@
 
 #include "./bitio.h"
 #include "./MD5.h"
+#include "./os.h"
 
 // internal constants
 
@@ -94,7 +95,6 @@ U8 swf_GetU8(TAG * t)
   #ifdef DEBUG_RFXSWF
     if (t->pos>=t->len) 
     { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
-      *(int*)0=0;
       return 0;
     }
   #endif
@@ -278,79 +278,118 @@ void swf_SetFixed8(TAG * t, float f)
   swf_SetU8(t, fr);
   swf_SetU8(t, (U8)f - (f<0 && fr!=0));
 }
-int swf_GetU30(TAG*tag)
+
+U32 swf_GetU30(TAG*tag)
 {
     U32 shift = 0;
     U32 s = 0;
+    int nr=0;
     while(1) {
        U8 b = swf_GetU8(tag);
+        nr++;
        s|=(b&127)<<shift;
        shift+=7;
-       if(!(b&128))
+       if(!(b&128) || shift>=32)
            break;
     }
+    /*int nr2= swf_SetU30(0, s);
+    if(nr!=nr2) {
+      printf("Unsigned value %d stored in %d bytes, I'd store it in %d bytes\n", s, nr, nr2);
+    }*/
     return s;
 }
-int swf_GetS30(TAG*tag)
+
+int swf_SetU30(TAG*tag, U32 u)
 {
-    U32 shift = 0;
-    U32 s = 0;
-    int nr=0;
-    while(1) {
-       U8 b = swf_GetU8(tag);
+    int nr = 0;
+    do {
+        if(tag)
+         swf_SetU8(tag, (u&~0x7f?0x80:0) | (u&0x7F));
+       u>>=7;
         nr++;
-       s|=(b&127)<<shift;
-       shift+=7;
-       if(!(b&128)) {
-            if(b&64) {
-                s|=0xffffffff<<shift;
-            }
-           break;
-        }
-    }
-    return s;
+    } while(u);
+    return nr;
+}
+
+void swf_SetABCU32(TAG*tag, U32 u)
+{
+  do {
+      swf_SetU8(tag, (u&~0x7f?0x80:0) | (u&0x7F));
+      u>>=7;
+  } while(u);
+}
+U32 swf_GetABCU32(TAG*tag)
+{
+  return swf_GetU30(tag);
+}
+void swf_SetABCS32(TAG*tag, S32 v)
+{
+  swf_SetABCU32(tag, v);
 }
-int swf_SetS30(TAG*tag, S32 s)
+S32 swf_GetABCS32(TAG*tag)
 {
+  return swf_GetABCU32(tag);
+}
+
+#if 0
+
+/*The AVM2 spec is just plain wrong, claiming that S32 values are sign
+extended. They're not.
+This wastes up to 4 bytes for every negative value. */
+
+void swf_SetABCS32(TAG*tag, S32 s)
+{
+  printf("write S32: %d\n", s);
     S32 neg = s<0?-1:0;
-    U8 sign = s<0?0x80:0;
-    int nr=0,pos=tag->len;
+    U8 sign = s<0?0x40:0;
     while(1) {
         U8 val = s&0x7f;
-        U8 vsign = s&0x80;
+        U8 vsign = s&0x40;
        s>>=7;
         neg>>=7;
         if(s==neg && vsign==sign) {
-            /* if the value we just wrote has the same sign as s
+            /* if the value we now write has the same sign as s
                and all the remaining bits are equal to the sign of s
                too, stop writing */
-            if(tag)
-             swf_SetU8(tag, val);
-            nr++;
+           swf_SetU8(tag, val);
+            printf("put %02x\n", val);
             break;
         } else {
-            if(tag)
-             swf_SetU8(tag, 0x80 | val);
-            nr++;
+            swf_SetU8(tag, 0x80 | val);
+            printf("put %02x\n", 0x80|val);
         }
     };
-    return nr;
-
 }
-int swf_SetU30(TAG*tag, U32 u)
+int swf_GetS30(TAG*tag)
 {
-    int nr = 0;
-    do {
-        if(tag)
-         swf_SetU8(tag, (u&~0x7f?0x80:0) | (u&0x7F));
-       u>>=7;
+    U32 shift = 0;
+    U32 s = 0;
+    int nr=0;
+    while(1) {
+       U8 b = swf_GetU8(tag);
         nr++;
-    } while(u);
-    return nr;
+       s|=(b&127)<<shift;
+       shift+=7;
+       if(!(b&128) || shift>=32) {
+            if(b&64) {
+                if(shift<32) 
+                  s|=0xffffffff<<shift;
+            }
+           break;
+        }
+    }
+    /* It's not uncommon for other applications (Flex for all negative numbers, and
+       Flash for -1) to generate a lot more bytes than would be necessary.
+       int nr2= swf_SetS30(0, s);
+    if(nr!=nr2) {
+      printf("Signed value %d stored in %d bytes, I'd store it in %d bytes\n", s, nr, nr2);
+    }*/
+    return s;
 }
-int swf_SetU30String(TAG*tag, const char*str)
+#endif
+
+int swf_SetU30String(TAG*tag, const char*str, int l)
 {
-    int l = strlen(str);
     int len=0;
     len+=swf_SetU30(tag, l);
     len+=l;
@@ -1443,6 +1482,17 @@ int swf_ReadSWF(int handle, SWF * swf)
   return swf_ReadSWF2(&reader, swf);
 }
 
+void swf_ReadABCfile(char*filename, SWF*swf)
+{
+    memset(swf, 0, sizeof(SWF));
+    swf->fileVersion=9;
+    swf->fileAttributes=1; //as3
+    TAG*tag = swf->firstTag = swf_InsertTag(0, ST_RAWABC);
+    memfile_t*file = memfile_open(filename);
+    swf_SetBlock(tag, file->data, file->len);
+    memfile_close(file);
+}
+
 int no_extra_tags = 0;
 
 int WriteExtraTags(SWF*swf, writer_t*writer)