/* * 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 "music-module.h" #include "upkg.h" struct music_mod { struct upkg_file *f; unsigned char header[64]; unsigned long hdrlen; }; int music_mod_init(void) { return 0; } void music_mod_exit(void) { } struct music_mod *music_mod_open(struct upkg_file *f) { struct music_mod *m; m = malloc(sizeof *m); if (!m) { return NULL; } m->f = f; m->hdrlen = upkg_export_read(f, m->header, sizeof m->header); return m; } void music_mod_close(struct music_mod *m) { free(m); } int music_mod_dump(struct music_mod *m, FILE *of) { unsigned char buf[1024]; size_t rc; if (upkg_export_seek(m->f, 0, SEEK_SET) != 0) { return -1; } while (1) { rc = upkg_export_read(m->f, buf, sizeof buf); if (rc == 0) { if (!m->f->eof) return -1; return 0; } if (fwrite(buf, rc, 1, of) != 1) { if (feof(of)) { fprintf(stderr, "unexpected end-of-file.\n"); } else { perror("fwrite"); } return -1; } if (rc < sizeof buf) { if (!m->f->eof) return -1; return 0; } } } int is_xm(unsigned char *buf, unsigned long len) { static const char head[15] = /* ASCII encoding of "Extended Module" */ "\x45\x78\x74\x65\x6e\x64\x65\x64\x20\x4d\x6f\x64\x75\x6c\x65"; if (len >= sizeof head && memcmp(head, buf, sizeof head) == 0) return 1; return 0; } int is_it(unsigned char *buf, unsigned long len) { static const char head[4] = /* ASCII encoding of "IMPM" */ "\x49\x4d\x50\x4d"; if (len >= sizeof head && memcmp(head, buf, sizeof head) == 0) return 1; return 0; } int is_s3m(unsigned char *buf, unsigned long len) { static const char head[4] = /* ASCII encoding of "SCRM" */ "\x53\x43\x52\x4d"; if (len < 0x2c + sizeof head) return 0; if (memcmp(head, buf+0x2c, sizeof head) == 0) return 1; return 0; } const char *music_mod_type(struct music_mod *mod) { if (is_xm(mod->header, mod->hdrlen)) return "xm"; if (is_it(mod->header, mod->hdrlen)) return "it"; if (is_s3m(mod->header, mod->hdrlen)) return "s3m"; return "unknown"; }