2 * upkg: tool for manipulating Unreal Tournament packages.
3 * Copyright (C) 2009 Nick Bowler
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <glib-object.h>
26 #include <uobject/uobject.h>
30 #define UOBJECT_GET_PRIV(o) \
31 G_TYPE_INSTANCE_GET_PRIVATE(o, UOBJECT_TYPE, struct uobject_priv)
51 struct uobject_property {
60 unsigned char buf[2048];
64 G_DEFINE_TYPE(UObject, uobject, G_TYPE_OBJECT);
67 get_real_size(unsigned long *real, unsigned size, unsigned char *buf, size_t n)
73 case 0: *real = 1; return 0;
74 case 1: *real = 2; return 0;
75 case 2: *real = 4; return 0;
76 case 3: *real = 12; return 0;
77 case 4: *real = 16; return 0;
84 *real = unpack_16_le(buf);
88 *real = unpack_32_le(buf);
96 decode_property(UObject *o, const char *name, struct upkg_file *f, unsigned long len)
98 struct uobject_priv *priv = UOBJECT_GET_PRIV(o);
99 unsigned long real_size, rc;
103 if (priv->nbuf-len < 1)
106 type = (priv->buf[len] >> 0) & 0x0f;
107 size = (priv->buf[len] >> 4) & 0x07;
108 top = (priv->buf[len] >> 7) & 0x01;
111 rc = get_real_size(&real_size, size, priv->buf, priv->nbuf-len);
118 if (priv->nbuf-len < 1)
120 g_value_init(&val, G_TYPE_UCHAR);
121 g_value_set_uchar(&val, priv->buf[len]);
122 g_object_set_property(G_OBJECT(o), name, &val);
124 case PROPERTY_INTEGER:
125 if (priv->nbuf-len < 4)
127 g_value_init(&val, G_TYPE_ULONG);
128 g_value_set_ulong(&val, unpack_32_le(priv->buf+len));
129 g_object_set_property(G_OBJECT(o), name, &val);
132 fprintf(stderr, "Unhandled property type %x\n", (unsigned)type);
136 if (real_size + len <= priv->nbuf) {
137 priv->nbuf -= real_size;
138 memmove(priv->buf, priv->buf+real_size, priv->nbuf);
140 long skip = real_size - priv->nbuf;
141 if (upkg_export_seek(f, skip, SEEK_CUR) != 0)
149 /* Deserialize properties from an Unreal package. */
150 static int deserialize(UObject *o, struct upkg_file *f)
152 struct uobject_priv *priv = UOBJECT_GET_PRIV(o);
153 unsigned long rc, tot_len = 0;
156 unsigned long len = 0;
160 /* Read some data into buffer. */
162 void *buf = priv->buf + priv->nbuf;
163 size_t amt = sizeof priv->buf - priv->nbuf;
164 rc = upkg_export_read(f, buf, amt);
170 /* Get the property name. */
171 rc = upkg_decode_index(&tmp, priv->buf+len, priv->nbuf-len);
176 name = upkg_get_name(f->pkg, tmp);
179 } else if (strcmp(name, "None") == 0) {
184 rc = decode_property(UOBJECT(o), name, f, len);
194 upkg_export_seek(f, 0, SEEK_SET);
199 int uobject_deserialize(GObject *obj, struct upkg *pkg, unsigned long idx)
201 g_return_val_if_fail(IS_UOBJECT(obj), -1);
202 UObject *uo = UOBJECT(obj);
206 g_return_val_if_fail(uo->pkg_file == NULL, -1);
207 f = upkg_export_open(pkg, idx);
212 rc = UOBJECT_GET_CLASS(obj)->deserialize(uo, f);
214 upkg_export_close(f);
224 static void uobject_init(UObject *o)
231 static void uobject_finalize(GObject *o)
233 UObject *uo = UOBJECT(o);
236 upkg_export_close(uo->pkg_file);
239 G_OBJECT_CLASS(uobject_parent_class)->finalize(o);
242 static void uobject_class_init(UObjectClass *class)
244 g_type_class_add_private(class, sizeof (struct uobject_priv));
245 GObjectClass *go = G_OBJECT_CLASS(class);
247 class->deserialize = deserialize;
248 go->finalize = uobject_finalize;