X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=interpreters%2Fbocfel%2Fblorb.c;fp=interpreters%2Fbocfel%2Fblorb.c;h=456e97655af0c2deb4a09154e5035a1f03be3b86;hb=3c59ba5eef5cb4d39c06eb7f523b9c3b026bdc9b;hp=0000000000000000000000000000000000000000;hpb=ed91d840318ed6ebfe3a5a77fa17114ddbf56640;p=projects%2Fchimara%2Fchimara.git diff --git a/interpreters/bocfel/blorb.c b/interpreters/bocfel/blorb.c new file mode 100644 index 0000000..456e976 --- /dev/null +++ b/interpreters/bocfel/blorb.c @@ -0,0 +1,121 @@ +/*- + * Copyright 2010-2012 Chris Spiegel. + * + * This file is part of Bocfel. + * + * Bocfel is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version + * 2 or 3, as published by the Free Software Foundation. + * + * Bocfel 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 Bocfel. If not, see . + */ + +#include +#include +#include + +#include "blorb.h" +#include "iff.h" +#include "io.h" + +struct zterp_blorb +{ + struct zterp_io *io; + struct zterp_iff *iff; + + size_t nchunks; + zterp_blorb_chunk *chunks; +}; + +struct zterp_blorb *zterp_blorb_parse(zterp_io *io) +{ + uint32_t size; + uint32_t nresources; + zterp_iff *iff; + struct zterp_blorb *blorb = NULL; + + iff = zterp_iff_parse(io, "IFRS"); + if(!zterp_iff_find(iff, "RIdx", &size)) goto err; + zterp_iff_free(iff); + + if(!zterp_io_read32(io, &nresources)) goto err; + + if((nresources * 12) + 4 != size) goto err; + + blorb = malloc(sizeof *blorb); + if(blorb == NULL) goto err; + + blorb->io = io; + blorb->nchunks = 0; + blorb->chunks = NULL; + + for(uint32_t i = 0; i < nresources; i++) + { + uint32_t usage, number, start, type; + zterp_blorb_chunk *new; + long saved; + uint32_t idx; + + if(!zterp_io_read32(io, &usage) || !zterp_io_read32(io, &number) || !zterp_io_read32(io, &start)) goto err; + + if(usage != BLORB_PICT && usage != BLORB_SND && usage != BLORB_EXEC) goto err; + + saved = zterp_io_tell(io); + if(saved == -1) goto err; + + if(zterp_io_seek(io, start, SEEK_SET) == -1) goto err; + + if(!zterp_io_read32(io, &type) || !zterp_io_read32(io, &size)) goto err; + + if(zterp_io_seek(io, saved, SEEK_SET) == -1) goto err; + + if(type == STRID("FORM")) + { + start -= 8; + size += 8; + } + + /* Not really efficient, but does it matter? */ + new = realloc(blorb->chunks, sizeof *new * ++blorb->nchunks); + if(new == NULL) goto err; + blorb->chunks = new; + + idx = blorb->nchunks - 1; + + new[idx].usage = usage; + new[idx].number = number; + new[idx].type = type; + memcpy(new[idx].name, IDSTR(type), 5); + new[idx].offset = start + 8; + new[idx].size = size; + } + + return blorb; + +err: + zterp_blorb_free(blorb); + + return NULL; +} + +void zterp_blorb_free(struct zterp_blorb *blorb) +{ + if(blorb != NULL) free(blorb->chunks); + free(blorb); +} + +const zterp_blorb_chunk *zterp_blorb_find(struct zterp_blorb *blorb, uint32_t usage, int number) +{ + for(size_t i = 0; i < blorb->nchunks; i++) + { + if(blorb->chunks[i].usage == usage && blorb->chunks[i].number == number) return &blorb->chunks[i]; + } + + return NULL; +}