diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_decompress.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_decompress.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_decompress.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_decompress.c new file mode 100644 index 0000000..90703f4 --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_decompress.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* $Id$ */ | ||
2 | |||
3 | /* | ||
4 | libg3d - 3D object loading library | ||
5 | |||
6 | Copyright (C) 2005-2009 Markus Dahms <mad@automagically.de> | ||
7 | |||
8 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Lesser General Public | ||
10 | License as published by the Free Software Foundation; either | ||
11 | version 2.1 of the License, or (at your option) any later version. | ||
12 | |||
13 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Lesser General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Lesser General Public | ||
19 | License along with this library; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <string.h> | ||
25 | #include <glib.h> | ||
26 | #include <g3d/stream.h> | ||
27 | |||
28 | #include "imp_ar.h" | ||
29 | |||
30 | #define AR_FLAG_COPIED 0x80 | ||
31 | #define AR_FLAG_COMPRESS 0x40 | ||
32 | |||
33 | guint8 *ar_decompress_chunk(guint8 *src, guint16 srcsize, guint16 *dstsize) | ||
34 | { | ||
35 | guint8 *dst = NULL, bit = 16; | ||
36 | gint32 i, j = 0, k, pos, size; | ||
37 | guint16 cmd; | ||
38 | |||
39 | #if DEBUG > 2 | ||
40 | printf("D: decompressing %d bytes chunk\n", srcsize); | ||
41 | #endif | ||
42 | |||
43 | if(src[0] == AR_FLAG_COPIED) | ||
44 | { | ||
45 | *dstsize = srcsize - 1; | ||
46 | dst = g_new0(guint8, *dstsize); | ||
47 | memcpy(dst, src + 1, *dstsize); | ||
48 | return dst; | ||
49 | } | ||
50 | |||
51 | *dstsize = 0; | ||
52 | cmd = (src[1] << 8) + src[2]; | ||
53 | for(i = 3; i < srcsize;) | ||
54 | { | ||
55 | if(bit == 0) | ||
56 | { | ||
57 | /* get new command */ | ||
58 | cmd = (src[i] << 8) + src[i + 1]; | ||
59 | i += 2; | ||
60 | bit = 16; | ||
61 | } | ||
62 | |||
63 | if(cmd & 0x8000) | ||
64 | { | ||
65 | pos = (src[i] << 4) + (src[i + 1] >> 4); | ||
66 | i ++; | ||
67 | if(pos != 0) | ||
68 | { | ||
69 | /* copy known chunk */ | ||
70 | size = (src[i] & 0xF) + 3; | ||
71 | *dstsize += size; | ||
72 | dst = g_realloc(dst, *dstsize); | ||
73 | i ++; | ||
74 | for(k = 0; k < size; k ++) | ||
75 | dst[j + k] = dst[j - pos + k]; | ||
76 | j += size; | ||
77 | } | ||
78 | else | ||
79 | { | ||
80 | /* RLE style... */ | ||
81 | size = (src[i] << 8) + src[i + 1] + 16; | ||
82 | *dstsize += size; | ||
83 | dst = g_realloc(dst, *dstsize); | ||
84 | i += 2; | ||
85 | for(k = 0; k < size; k ++) | ||
86 | dst[j + k] = src[i]; | ||
87 | i ++; | ||
88 | j += size; | ||
89 | } | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | /* plain copy */ | ||
94 | *dstsize += 1; | ||
95 | dst = g_realloc(dst, *dstsize); | ||
96 | dst[j] = src[i]; | ||
97 | i ++; | ||
98 | j ++; | ||
99 | } | ||
100 | |||
101 | cmd <<= 1; | ||
102 | bit --; | ||
103 | } | ||
104 | |||
105 | return dst; | ||
106 | } | ||
107 | |||
108 | gboolean ar_decompress_to_file(G3DStream *stream, ArDirEntry *dirent) | ||
109 | { | ||
110 | FILE *o; | ||
111 | gchar cmd; | ||
112 | guint32 size; | ||
113 | guint16 srcsize, dstsize; | ||
114 | guint8 *src, *dst; | ||
115 | |||
116 | o = fopen(dirent->name, "wb"); | ||
117 | if(o == NULL) { | ||
118 | g_warning("failed to write to '%s'", dirent->name); | ||
119 | return FALSE; | ||
120 | } | ||
121 | |||
122 | /* seek to file start */ | ||
123 | g3d_stream_seek(stream, dirent->offset, G_SEEK_SET); | ||
124 | |||
125 | /* skip tags */ | ||
126 | do { | ||
127 | cmd = g3d_stream_read_int8(stream); | ||
128 | if(cmd != 'D') { | ||
129 | size = g3d_stream_read_int32_le(stream); | ||
130 | g3d_stream_skip(stream, size); | ||
131 | } | ||
132 | } while(cmd != 'D'); | ||
133 | |||
134 | #if DEBUG > 2 | ||
135 | printf("D: starting decompression part\n"); | ||
136 | #endif | ||
137 | |||
138 | /* decompress stuff */ | ||
139 | while(1) { | ||
140 | srcsize = g3d_stream_read_int16_le(stream); | ||
141 | if(srcsize == 0) | ||
142 | break; | ||
143 | |||
144 | src = g_new0(guint8, srcsize); | ||
145 | g3d_stream_read(stream, src, srcsize); | ||
146 | dst = ar_decompress_chunk(src, srcsize, &dstsize); | ||
147 | |||
148 | if(dstsize > 0) { | ||
149 | fwrite(dst, 1, dstsize, o); | ||
150 | g_free(dst); | ||
151 | } | ||
152 | |||
153 | g_free(src); | ||
154 | } | ||
155 | |||
156 | fclose(o); | ||
157 | |||
158 | return TRUE; | ||
159 | } | ||
160 | |||
161 | |||