%alltop{ /* * upkg: tool for manipulating Unreal Tournament packages. * Copyright © 2011 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ %} %{ #include #include #include #include #include "pack.h" %} %h{ #include %} class Engine:Sound from U:Object (dynamic) (interface U:Object:Exportable) { interface U:Object:Exportable private int export(U:Object *uo, FILE *outf) { struct upkg_file *f = uo->pkg_file; unsigned char buf[1024]; size_t buflen; if (upkg_export_seek(f, 0, SEEK_SET) != 0) return -1; do { buflen = upkg_export_read(f, buf, sizeof buf); if (fwrite(buf, buflen, 1, outf) != 1) return -1; } while (buflen == sizeof buf); if (!f->eof) return -1; return 0; } interface U:Object:Exportable private int export_name(U:Object *uo, char *buf, size_t n) { return snprintf(buf, n, "%s.wav", uo->pkg_file->name); } override (U:Object) int deserialize(U:Object *uo) { struct upkg_file *f = uo->pkg_file; size_t rc, pos = 0, buflen; unsigned char buf[32]; unsigned long end_offset; const char *fmt_name; long size, fmt; PARENT_HANDLER(uo); buflen = upkg_export_read(f, buf, sizeof buf); /* This seems to be the name of the format. The only format * that actually gets used is WAV, so we can check that. */ rc = upkg_decode_index(&fmt, buf+pos, buflen-pos); if (rc == 0) return -1; pos += rc; fmt_name = upkg_get_name(f->pkg, fmt); if (!fmt_name || strcasecmp(fmt_name, "wav") != 0) { u_err(uo, "format name is not WAV"); return -1; } /* Like textures, there's an (apparently useless) offset to * the end of the sound data which is implied by the next * field. Just validate it. */ if (f->pkg->version >= 63) { if (pos + 4 > buflen) return -1; end_offset = unpack_32_le(buf+pos); pos += 4; } rc = upkg_decode_index(&size, buf+pos, buflen-pos); if (rc == 0 || size < 0 || size > f->len - pos) return -1; pos += rc; f->base += pos; f->len = size; upkg_export_seek(f, 0, SEEK_SET); if (f->pkg->version >= 63) { if (end_offset != f->base + f->len) { u_err(uo, "end offset does not match size"); return -1; } } return 0; } }