2012-03-04 13:28:34 -06:00
|
|
|
/*
|
2012-05-21 23:27:44 -05:00
|
|
|
FileHandler - General-purpose file handling library for Niotso
|
|
|
|
iff.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
|
|
|
Author(s): Fatbag <X-Fi6@phppoll.org>
|
|
|
|
Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
|
2012-03-04 13:28:34 -06:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2012-06-14 09:19:13 -05:00
|
|
|
#include "iffparser.h"
|
2012-03-04 13:28:34 -06:00
|
|
|
|
2012-04-29 00:44:41 -05:00
|
|
|
/****
|
|
|
|
** Supported Chunks
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define iff_register(x) \
|
|
|
|
int iff_parse_##x(IFFChunk *, const uint8_t *); \
|
|
|
|
void iff_free_##x(void *)
|
|
|
|
|
|
|
|
iff_register(bcon);
|
2012-06-15 10:18:12 -05:00
|
|
|
iff_register(dgrp);
|
2012-04-29 00:44:41 -05:00
|
|
|
iff_register(str);
|
2012-05-21 23:27:44 -05:00
|
|
|
iff_register(cats);
|
|
|
|
iff_register(c_string);
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_register(glob);
|
|
|
|
iff_register(fcns);
|
2012-05-25 15:48:09 -05:00
|
|
|
iff_register(palt);
|
2012-06-15 20:45:11 -05:00
|
|
|
iff_register(bhav);
|
2012-06-15 10:18:12 -05:00
|
|
|
iff_register(objf);
|
2012-05-28 23:37:38 -05:00
|
|
|
iff_register(spr);
|
2012-06-15 10:18:12 -05:00
|
|
|
iff_register(spr2);
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_register(tmpl);
|
2012-04-29 00:44:41 -05:00
|
|
|
iff_register(trcn);
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_register(rsmp);
|
2012-04-29 00:44:41 -05:00
|
|
|
|
2012-05-21 23:27:44 -05:00
|
|
|
/* The ordering of these chunk types must match throughout this block: */
|
2012-04-29 00:44:41 -05:00
|
|
|
const char chunktypes[] =
|
2012-05-21 23:27:44 -05:00
|
|
|
"STR#" "CTSS" "FAMs" "TTAs" "CST\0"
|
|
|
|
"CATS"
|
|
|
|
"FWAV"
|
2012-05-24 01:53:56 -05:00
|
|
|
"GLOB"
|
2012-04-29 00:44:41 -05:00
|
|
|
"BCON"
|
2012-05-24 01:53:56 -05:00
|
|
|
"FCNS"
|
2012-05-25 15:48:09 -05:00
|
|
|
"PALT"
|
2012-05-28 23:37:38 -05:00
|
|
|
"SPR#"
|
2012-06-15 10:18:12 -05:00
|
|
|
"SPR2"
|
|
|
|
"DGRP"
|
2012-05-24 01:53:56 -05:00
|
|
|
"TMPL"
|
2012-04-29 00:44:41 -05:00
|
|
|
"TRCN"
|
2012-06-15 20:45:11 -05:00
|
|
|
"BHAV"
|
2012-06-15 10:18:12 -05:00
|
|
|
"OBJf"
|
2012-05-24 01:53:56 -05:00
|
|
|
"rsmp"
|
2012-04-29 00:44:41 -05:00
|
|
|
;
|
|
|
|
int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
|
2012-05-21 23:27:44 -05:00
|
|
|
iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str,
|
|
|
|
iff_parse_cats,
|
|
|
|
iff_parse_c_string,
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_parse_glob,
|
2012-04-29 00:44:41 -05:00
|
|
|
iff_parse_bcon,
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_parse_fcns,
|
2012-05-25 15:48:09 -05:00
|
|
|
iff_parse_palt,
|
2012-05-28 23:37:38 -05:00
|
|
|
iff_parse_spr,
|
2012-06-15 10:18:12 -05:00
|
|
|
iff_parse_spr2,
|
|
|
|
iff_parse_dgrp,
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_parse_tmpl,
|
|
|
|
iff_parse_trcn,
|
2012-06-15 20:45:11 -05:00
|
|
|
iff_parse_bhav,
|
2012-06-15 10:18:12 -05:00
|
|
|
iff_parse_objf,
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_parse_rsmp
|
2012-04-29 00:44:41 -05:00
|
|
|
};
|
|
|
|
void (* const iff_free_function[])(void*) = {
|
2012-05-21 23:27:44 -05:00
|
|
|
iff_free_str, iff_free_str, iff_free_str, iff_free_str, iff_free_str,
|
|
|
|
iff_free_cats,
|
|
|
|
NULL,
|
2012-05-24 01:53:56 -05:00
|
|
|
NULL,
|
2012-04-29 00:44:41 -05:00
|
|
|
iff_free_bcon,
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_free_fcns,
|
2012-05-25 15:48:09 -05:00
|
|
|
NULL,
|
2012-05-28 23:37:38 -05:00
|
|
|
iff_free_spr,
|
2012-06-15 10:18:12 -05:00
|
|
|
iff_free_spr,
|
|
|
|
iff_free_dgrp,
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_free_tmpl,
|
|
|
|
iff_free_trcn,
|
2012-06-15 20:45:11 -05:00
|
|
|
iff_free_bhav,
|
2012-06-15 10:18:12 -05:00
|
|
|
iff_free_objf,
|
2012-05-24 01:53:56 -05:00
|
|
|
iff_free_rsmp
|
2012-04-29 00:44:41 -05:00
|
|
|
};
|
|
|
|
/* End */
|
|
|
|
|
|
|
|
|
|
|
|
/****
|
|
|
|
** API public functions
|
|
|
|
*/
|
2012-03-04 13:28:34 -06:00
|
|
|
|
2012-11-11 17:10:53 -06:00
|
|
|
int iff_create(IFFFile * IFFFileInfo)
|
2012-03-04 13:28:34 -06:00
|
|
|
{
|
2012-11-11 17:10:53 -06:00
|
|
|
memset(IFFFileInfo, 0, sizeof(IFFFile));
|
2012-05-21 23:27:44 -05:00
|
|
|
|
2012-11-11 17:10:53 -06:00
|
|
|
IFFFileInfo->Chunks = calloc(1, sizeof(IFFChunk));
|
|
|
|
if(IFFFileInfo->Chunks == NULL)
|
|
|
|
return 0;
|
|
|
|
IFFFileInfo->SizeAllocated = sizeof(IFFChunk);
|
|
|
|
|
|
|
|
return 1;
|
2012-03-04 13:28:34 -06:00
|
|
|
}
|
|
|
|
|
2012-04-06 13:27:40 -05:00
|
|
|
int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize)
|
2012-03-04 13:28:34 -06:00
|
|
|
{
|
|
|
|
unsigned offset;
|
|
|
|
|
|
|
|
if(!FileSize) FileSize = ~0;
|
|
|
|
else if(FileSize < 64)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if(memcmp(Buffer, Header_IFF, 60))
|
|
|
|
return 0;
|
|
|
|
memcpy(IFFFileInfo->Header, Buffer, 60);
|
|
|
|
|
|
|
|
offset = read_uint32be(Buffer+60);
|
|
|
|
if(offset > FileSize - 28)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-04-29 00:44:41 -05:00
|
|
|
IFFChunk * iff_add_chunk(IFFFile * IFFFileInfo)
|
2012-03-04 13:28:34 -06:00
|
|
|
{
|
2012-04-29 00:44:41 -05:00
|
|
|
if((IFFFileInfo->ChunkCount+1)*sizeof(IFFChunk) > IFFFileInfo->SizeAllocated){
|
|
|
|
IFFChunk * ptr;
|
|
|
|
if(IFFFileInfo->SizeAllocated > SIZE_MAX/2) return NULL;
|
|
|
|
ptr = realloc(IFFFileInfo->Chunks, IFFFileInfo->SizeAllocated<<1);
|
|
|
|
if(ptr == NULL) return NULL;
|
2012-05-21 23:27:44 -05:00
|
|
|
|
2012-04-29 00:44:41 -05:00
|
|
|
IFFFileInfo->Chunks = ptr;
|
|
|
|
IFFFileInfo->SizeAllocated<<=1;
|
2012-03-04 13:28:34 -06:00
|
|
|
}
|
2012-04-06 13:27:40 -05:00
|
|
|
|
2012-05-21 23:27:44 -05:00
|
|
|
return &IFFFileInfo->Chunks[IFFFileInfo->ChunkCount++];
|
2012-03-04 13:28:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize)
|
|
|
|
{
|
|
|
|
if(MaxChunkSize == 0) MaxChunkSize = ~0;
|
|
|
|
|
|
|
|
if(MaxChunkSize < 76)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
memcpy(ChunkInfo->Type, Buffer+0, 4);
|
2012-04-29 00:44:41 -05:00
|
|
|
ChunkInfo->Type[4] = 0x00;
|
2012-03-04 13:28:34 -06:00
|
|
|
ChunkInfo->Size = read_uint32be(Buffer+4);
|
|
|
|
ChunkInfo->ChunkID = read_uint16be(Buffer+8);
|
|
|
|
ChunkInfo->Flags = read_uint16be(Buffer+10);
|
|
|
|
memcpy(ChunkInfo->Label, Buffer+12, 64);
|
|
|
|
|
|
|
|
if(ChunkInfo->Size < 76 || ChunkInfo->Size > MaxChunkSize)
|
|
|
|
return 0;
|
|
|
|
|
2012-06-14 09:19:13 -05:00
|
|
|
ChunkInfo->Size -= 76;
|
|
|
|
|
|
|
|
if(ChunkInfo->Size){
|
|
|
|
ChunkInfo->Data = malloc(ChunkInfo->Size);
|
2012-03-04 13:28:34 -06:00
|
|
|
if(ChunkInfo->Data == NULL)
|
|
|
|
return 0;
|
2012-06-14 09:19:13 -05:00
|
|
|
memcpy(ChunkInfo->Data, Buffer+76, ChunkInfo->Size);
|
2012-03-04 13:28:34 -06:00
|
|
|
}
|
2012-05-21 23:27:44 -05:00
|
|
|
ChunkInfo->FormattedData = NULL;
|
2012-03-04 13:28:34 -06:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize)
|
|
|
|
{
|
|
|
|
while(BufferSize){
|
2012-04-29 00:44:41 -05:00
|
|
|
IFFChunk * chunk = iff_add_chunk(IFFFileInfo);
|
2012-03-04 13:28:34 -06:00
|
|
|
if(chunk == NULL)
|
|
|
|
return 0;
|
2012-04-29 00:44:41 -05:00
|
|
|
if(!iff_read_chunk(chunk, Buffer, BufferSize))
|
2012-03-04 13:28:34 -06:00
|
|
|
return 0;
|
|
|
|
|
2012-06-14 09:19:13 -05:00
|
|
|
Buffer += chunk->Size + 76;
|
|
|
|
BufferSize -= chunk->Size + 76;
|
2012-03-04 13:28:34 -06:00
|
|
|
}
|
|
|
|
return 1;
|
2012-04-29 00:44:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
|
|
|
unsigned i;
|
|
|
|
for(i=0; chunktypes[i*4] != '\0'; i++){
|
|
|
|
if(!memcmp(ChunkInfo->Type, chunktypes+i*4, 4)){
|
|
|
|
if(iff_parse_function[i](ChunkInfo, Buffer)) return 1;
|
2012-05-21 23:27:44 -05:00
|
|
|
iff_free_chunk(ChunkInfo);
|
2012-04-29 00:44:41 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-28 23:37:38 -05:00
|
|
|
IFFChunk * iff_find_chunk(IFFFile * IFFFileInfo, const char * Type, int ChunkID){
|
|
|
|
unsigned i;
|
|
|
|
for(i=0; i<IFFFileInfo->ChunkCount; i++){
|
|
|
|
IFFChunk * Chunk = &IFFFileInfo->Chunks[i];
|
|
|
|
if((Type == NULL || !strcmp(Chunk->Type, Type)) &&
|
|
|
|
(ChunkID == -1 || Chunk->ChunkID == ChunkID))
|
|
|
|
return Chunk;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-04-29 00:44:41 -05:00
|
|
|
void iff_free_chunk(IFFChunk * ChunkInfo){
|
|
|
|
unsigned i;
|
2012-05-21 23:27:44 -05:00
|
|
|
if(ChunkInfo == NULL || ChunkInfo->FormattedData == NULL) return;
|
2012-04-29 00:44:41 -05:00
|
|
|
|
|
|
|
for(i=0; chunktypes[i*4] != '\0'; i++){
|
|
|
|
if(!memcmp(ChunkInfo->Type, chunktypes+i*4, 4)){
|
|
|
|
if(iff_free_function[i])
|
|
|
|
iff_free_function[i](ChunkInfo->FormattedData);
|
|
|
|
free(ChunkInfo->FormattedData);
|
2012-05-21 23:27:44 -05:00
|
|
|
ChunkInfo->FormattedData = NULL;
|
2012-04-29 00:44:41 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void iff_delete(IFFFile * IFFFileInfo){
|
|
|
|
unsigned i;
|
|
|
|
if(IFFFileInfo == NULL) return;
|
|
|
|
|
|
|
|
if(IFFFileInfo->Chunks != NULL){
|
|
|
|
for(i=0; i<IFFFileInfo->ChunkCount; i++){
|
|
|
|
iff_free_chunk(IFFFileInfo->Chunks+i);
|
|
|
|
free(IFFFileInfo->Chunks[i].Data);
|
|
|
|
}
|
|
|
|
free(IFFFileInfo->Chunks);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(IFFFileInfo->ResourceMap != NULL){
|
|
|
|
free(IFFFileInfo->ResourceMap->Data);
|
|
|
|
free(IFFFileInfo->ResourceMap->FormattedData);
|
|
|
|
free(IFFFileInfo->ResourceMap);
|
|
|
|
}
|
2012-03-04 13:28:34 -06:00
|
|
|
}
|