%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;
}
}