3 * upkg: tool for manipulating Unreal Tournament packages.
4 * Copyright © 2012, 2022 Nick Bowler
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29 #include <uobject/exportable.h>
34 #include <uobject/uobject.h>
37 class Engine:Sound from U:Object (dynamic)
38 (interface U:Object:Exportable)
40 interface U:Object:Exportable
41 private int export(U:Object *uo, FILE *outf)
43 struct upkg_file *f = uo->pkg_file;
44 unsigned char buf[1024];
47 if (upkg_export_seek(f, 0, SEEK_SET) != 0)
51 buflen = upkg_export_read(f, buf, sizeof buf);
52 if (fwrite(buf, buflen, 1, outf) != 1)
54 } while (buflen == sizeof buf);
61 interface U:Object:Exportable
62 private int export_name(U:Object *uo, char *buf, size_t n)
64 return snprintf(buf, n, "%s.wav", uo->pkg_file->name);
67 override (U:Object) int deserialize(U:Object *uo)
69 struct upkg_file *f = uo->pkg_file;
70 size_t rc, pos = 0, buflen;
71 unsigned char buf[32];
72 unsigned long end_offset;
78 buflen = upkg_export_read(f, buf, sizeof buf);
80 /* This seems to be the name of the format. The only format
81 * that actually gets used is WAV, so we can check that. */
82 rc = upkg_decode_index(&fmt, buf+pos, buflen-pos);
87 fmt_name = upkg_get_name(f->pkg, fmt);
88 if (!fmt_name || strcasecmp(fmt_name, "wav") != 0) {
89 u_err(uo, "format name is not WAV");
93 /* Like textures, there's an (apparently useless) offset to
94 * the end of the sound data which is implied by the next
95 * field. Just validate it. */
96 if (f->pkg->version >= 63) {
99 end_offset = unpack_32_le(buf+pos);
103 rc = upkg_decode_index(&size, buf+pos, buflen-pos);
104 if (rc == 0 || size < 0 || size > f->len - pos)
110 upkg_export_seek(f, 0, SEEK_SET);
112 if (f->pkg->version >= 63) {
113 if (end_offset != f->base + f->len) {
114 u_err(uo, "end offset does not match size");