aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_decompress.c
diff options
context:
space:
mode:
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.c161
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
33guint8 *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
108gboolean 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