From f9bb95dd805cfa519717d39eda8a4cad40709fc3 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Sun, 20 May 2012 00:11:52 -0400 Subject: [PATCH] engine: Implement Engine.Sound. This one's pretty trivial; but now we can export sounds. MMM-M-M-M-M-MONSTER KILL! --- Makefile.am | 2 +- src/engine/.gitignore | 1 + src/engine/engine.c | 2 + src/engine/sound.gob | 117 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/engine/sound.gob diff --git a/Makefile.am b/Makefile.am index fda4993..1fc339f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,7 +56,7 @@ $(libuobject_la): $(LTDLDEPS) moduleflags = -module -avoid-version -export-symbols-regex _LTX_ engine_GOBS = src/engine/palette.gob src/engine/texture.gob \ - src/engine/music.gob + src/engine/music.gob src/engine/sound.gob MAINTAINERCLEANFILES += $(engine_GOBS:.gob=.gobstamp) \ $(engine_GOBS:.gob=.c) $(engine_GOBS:.gob=.h) diff --git a/src/engine/.gitignore b/src/engine/.gitignore index 85b5830..5b468a1 100644 --- a/src/engine/.gitignore +++ b/src/engine/.gitignore @@ -1,3 +1,4 @@ palette.[ch] texture.[ch] +sound.[ch] music.[ch] diff --git a/src/engine/engine.c b/src/engine/engine.c index 3bf27e7..92cc0c3 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -22,6 +22,7 @@ #include #include #include +#include #define init engine_LTX_init #define exit engine_LTX_exit @@ -29,6 +30,7 @@ int init(GTypeModule *m) { engine_music_register_type(m); + engine_sound_register_type(m); engine_texture_register_type(m); engine_palette_register_type(m); return 0; 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; + } +} -- 2.43.2