%alltop{ /* * upkg: tool for manipulating Unreal Tournament packages. * Copyright © 2009-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 #include %} %h{ #include %} class Engine:Music from U:Object (dynamic) (interface U:Object:Exportable) (interface U:Object:Loadable) { private struct music_mod *mod = NULL; private unsigned loaded = 0; interface U:Object:Loadable private int load(U:Object *uo) { struct upkg_file *f = uo->pkg_file; Self *self = SELF(uo); if (!self->_priv->loaded) { g_return_val_if_fail(f != NULL, -1); if (upkg_export_seek(f, 0, SEEK_SET) != 0) return -1; self->_priv->mod = music_mod_open(f); if (!self->_priv->mod) return -1; } self->_priv->loaded++; return 0; } interface U:Object:Loadable private void unload(U:Object *uo) { Self *self = SELF(uo); g_return_if_fail(self->_priv->loaded > 0); if (--self->_priv->loaded == 0) music_mod_close(self->_priv->mod); } interface U:Object:Exportable private int export(U:Object *uo, FILE *f) { Self *self = SELF(uo); int rc; if (self_load(uo) != 0) return -1; rc = music_mod_dump(self->_priv->mod, f); self_unload(uo); return rc; } interface U:Object:Exportable private int export_name(U:Object *uo, char *buf, size_t n) { Self *self = SELF(uo); const char *type; int rc; if (self_load(uo) != 0) { if (n > 0) buf[0] = '\0'; return 0; } type = music_mod_type(self->_priv->mod); rc = snprintf(buf, n, "%s.%s", uo->pkg_file->name, type); self_unload(uo); return rc; } override (U:Object) int deserialize(U:Object *uo) { struct upkg_file *f = uo->pkg_file; Self *self = SELF(uo); size_t rc, pos, buflen; unsigned char buf[32]; long size; PARENT_HANDLER(uo); buflen = upkg_export_read(f, buf, sizeof buf); /* Unknown field #1 */ if (buflen - pos < 1) return -1; pos += 1; if (uo->pkg->version > 61) { /* Unknown field #2 */ if (buflen - pos < 4) return -1; pos += 4; } rc = upkg_decode_index(&size, buf+pos, buflen-pos); if (rc == 0 || size < 0) return -1; pos += rc; f->base += pos; f->len = size; upkg_export_seek(f, 0, SEEK_SET); return 0; } }