X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/4165687b9036344270342acae34fe5086b0bf949..f9bb95dd805cfa519717d39eda8a4cad40709fc3:/src/engine/sound.gob diff --git a/src/engine/sound.gob b/src/engine/sound.gob new file mode 100644 index 0000000..fd0a060 --- /dev/null +++ b/src/engine/sound.gob @@ -0,0 +1,117 @@ +%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; + } +}