mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-04 13:47:04 -04:00
zTSO
- Added libraries from formats and libvitaboy
This commit is contained in:
parent
66ce473514
commit
5efdb29315
101 changed files with 11711 additions and 10889 deletions
37
library/formats/iff/CMakeLists.txt
Normal file
37
library/formats/iff/CMakeLists.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
project(iff)
|
||||
|
||||
set(IFF_SOURCES
|
||||
bhav.c
|
||||
cats.c
|
||||
iff.c
|
||||
bcon.c
|
||||
dgrp.c
|
||||
fcns.c
|
||||
glob.c
|
||||
objf.c
|
||||
palt.c
|
||||
rsmp.c
|
||||
spr.c
|
||||
spr2.c
|
||||
str.c
|
||||
string.c
|
||||
tmpl.c
|
||||
trcn.c
|
||||
)
|
||||
|
||||
add_library(iff_static STATIC ${IFF_SOURCES})
|
||||
set_target_properties(iff_static PROPERTIES
|
||||
OUTPUT_NAME "iff"
|
||||
PREFIX ""
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
#### Shared library (uncomment to build)
|
||||
#add_library(iff_shared SHARED ${IFF_SOURCES})
|
||||
#set_target_properties(iff_shared PROPERTIES
|
||||
# OUTPUT_NAME "iff"
|
||||
# PREFIX ""
|
||||
# CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
add_executable(iffexport iffexport.c)
|
||||
target_link_libraries(iffexport iff_static)
|
53
library/formats/iff/bcon.c
Normal file
53
library/formats/iff/bcon.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
bcon.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
|
||||
Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFF_BCON *BCONData;
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 2)
|
||||
return 0;
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFF_BCON));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
BCONData = ChunkInfo->FormattedData;
|
||||
BCONData->ConstantCount = read_uint8le(Buffer);
|
||||
BCONData->Flags = read_uint8le(Buffer + 1);
|
||||
if(BCONData->ConstantCount == 0)
|
||||
return 1;
|
||||
if(BCONData->ConstantCount * 2 /* bytes */ > ChunkInfo->Size - 2)
|
||||
return 0;
|
||||
|
||||
BCONData->Constants = malloc(BCONData->ConstantCount * sizeof(uint16_t));
|
||||
if(BCONData->Constants == NULL)
|
||||
return 0;
|
||||
|
||||
Buffer += 2;
|
||||
for(i=0; i<BCONData->ConstantCount; i++, Buffer += 2)
|
||||
BCONData->Constants[i] = read_uint16le(Buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_bcon(void * FormattedData){
|
||||
IFF_BCON *BCONData = FormattedData;
|
||||
free(BCONData->Constants);
|
||||
}
|
91
library/formats/iff/bhav.c
Normal file
91
library/formats/iff/bhav.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
bhav.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
|
||||
Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
#define HEADER_SIZE (12 + (Behavior->Version == 0x8003))
|
||||
|
||||
int iff_parse_bhav(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFBehavior *Behavior;
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 12)
|
||||
return 0;
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFBehavior));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
Behavior = ChunkInfo->FormattedData;
|
||||
Behavior->Version = read_uint16le(Buffer);
|
||||
if(Behavior->Version < 0x8000 || Behavior->Version > 0x8003 || (Behavior->Version == 0x8003 && ChunkInfo->Size < 13))
|
||||
return 0;
|
||||
|
||||
switch(Behavior->Version){
|
||||
case 0x8000: {
|
||||
Behavior->InstructionCount = read_uint16le(Buffer+2);
|
||||
} break;
|
||||
|
||||
case 0x8001: {
|
||||
Behavior->InstructionCount = read_uint16le(Buffer+2);
|
||||
} break;
|
||||
|
||||
case 0x8002: {
|
||||
Behavior->InstructionCount = read_uint16le(Buffer+2);
|
||||
Behavior->Type = read_uint8le(Buffer+4);
|
||||
Behavior->ArgumentCount = read_uint8le(Buffer+5);
|
||||
Behavior->LocalCount = read_uint16le(Buffer+6);
|
||||
Behavior->Flags = read_uint16le(Buffer+8);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
Behavior->Type = read_uint8le(Buffer+2);
|
||||
Behavior->ArgumentCount = read_uint8le(Buffer+3);
|
||||
Behavior->LocalCount = read_uint8le(Buffer+4);
|
||||
Behavior->Flags = read_uint16le(Buffer+7);
|
||||
Behavior->InstructionCount = read_uint32le(Buffer+9);
|
||||
} break;
|
||||
}
|
||||
|
||||
if(Behavior->InstructionCount == 0)
|
||||
return 1;
|
||||
if(Behavior->InstructionCount > 255 || Behavior->InstructionCount*12 > ChunkInfo->Size - HEADER_SIZE)
|
||||
return 0;
|
||||
|
||||
Behavior->Instructions = calloc(Behavior->InstructionCount, sizeof(IFFInstruction));
|
||||
if(Behavior->Instructions == NULL)
|
||||
return 0;
|
||||
|
||||
Buffer += HEADER_SIZE;
|
||||
|
||||
for(i=0; i<Behavior->InstructionCount; i++){
|
||||
Behavior->Instructions[i].Opcode = read_uint16le(Buffer);
|
||||
Behavior->Instructions[i].TDest = read_uint8le(Buffer+2);
|
||||
Behavior->Instructions[i].FDest = read_uint8le(Buffer+3);
|
||||
memcpy(Behavior->Instructions[i].Operands, Buffer+4, 8);
|
||||
|
||||
Buffer += 12;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_bhav(void * FormattedData){
|
||||
IFFBehavior *Behavior = FormattedData;
|
||||
free(Behavior->Instructions);
|
||||
}
|
38
library/formats/iff/cats.c
Normal file
38
library/formats/iff/cats.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
cats.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_cats(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFStringPair * StringData;
|
||||
bytestream b;
|
||||
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFStringPair));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
StringData = ChunkInfo->FormattedData;
|
||||
return (read_c_string(&b, &StringData->Key) && read_c_string(&b, &StringData->Value));
|
||||
}
|
||||
|
||||
void iff_free_cats(void * FormattedData){
|
||||
IFFStringPair * StringData = FormattedData;
|
||||
free(StringData->Key);
|
||||
free(StringData->Value);
|
||||
}
|
108
library/formats/iff/dgrp.c
Normal file
108
library/formats/iff/dgrp.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
dgrp.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
#define read_split(x, y, z) \
|
||||
(largefields ? read_uint##z(x) : read_uint##y(x))
|
||||
|
||||
int iff_parse_dgrp(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFDrawGroup *Group;
|
||||
bytestream b;
|
||||
int largefields;
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 52)
|
||||
return 0;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFDrawGroup));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
Group = ChunkInfo->FormattedData;
|
||||
Group->Version = read_uint16(&b);
|
||||
if(Group->Version < 20000 || Group->Version > 20004 || Group->Version == 20002)
|
||||
return 0;
|
||||
largefields = (Group->Version >= 20003);
|
||||
Group->AngleCount = read_split(&b, 16, 32);
|
||||
if(Group->AngleCount != 12)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<12; i++){
|
||||
IFFDrawAngle * Angle = &Group->DrawAngles[i];
|
||||
unsigned j;
|
||||
|
||||
if(b.Size < ((!largefields) ? 4 : 12))
|
||||
return 0;
|
||||
|
||||
if(!largefields)
|
||||
Angle->SpriteCount = read_uint16(&b);
|
||||
Angle->Direction = read_split(&b, 8, 32);
|
||||
Angle->Zoom = read_split(&b, 8, 32);
|
||||
if(largefields)
|
||||
Angle->SpriteCount = read_uint32(&b);
|
||||
|
||||
if((Angle->Direction != 1 && Angle->Direction != 4 && Angle->Direction != 16 && Angle->Direction != 64)
|
||||
|| (!Angle->Zoom || Angle->Zoom > 3))
|
||||
return 0;
|
||||
if(Angle->SpriteCount == 0)
|
||||
continue;
|
||||
|
||||
Angle->SpriteInfo = calloc(Angle->SpriteCount, sizeof(IFFSpriteInfo));
|
||||
if(Angle->SpriteInfo == NULL)
|
||||
return 0;
|
||||
|
||||
for(j=0; j<Angle->SpriteCount; j++){
|
||||
IFFSpriteInfo * Sprite = &Angle->SpriteInfo[j];
|
||||
const uint8_t size[5] = {12, 16, 0, 24, 32};
|
||||
|
||||
if(b.Size < size[Group->Version - 20000])
|
||||
return 0;
|
||||
|
||||
if(!largefields)
|
||||
Sprite->Type = read_uint16(&b);
|
||||
Sprite->ChunkID = read_split(&b, 16, 32);
|
||||
Sprite->SpriteIndex = read_split(&b, 16, 32);
|
||||
if(!largefields)
|
||||
Sprite->Flags = read_uint16(&b);
|
||||
Sprite->SpriteX = read_split(&b, 16, 32);
|
||||
Sprite->SpriteY = read_split(&b, 16, 32);
|
||||
if(Group->Version >= 20001){
|
||||
Sprite->ObjectZ = read_float(&b);
|
||||
if(Group->Version >= 20003){
|
||||
Sprite->Flags = read_uint32(&b);
|
||||
if(Group->Version == 20004){
|
||||
Sprite->ObjectX = read_float(&b);
|
||||
Sprite->ObjectY = read_float(&b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_dgrp(void * FormattedData){
|
||||
IFFDrawGroup *Group = FormattedData;
|
||||
int i;
|
||||
for(i=0; i<12; i++){
|
||||
IFFDrawAngle *Angle = &Group->DrawAngles[i];
|
||||
free(Angle->SpriteInfo);
|
||||
}
|
||||
}
|
86
library/formats/iff/fcns.c
Normal file
86
library/formats/iff/fcns.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
fcns.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_fcns(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFConstantList *List;
|
||||
bytestream b;
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 16)
|
||||
return 0;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFConstantList));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
List = ChunkInfo->FormattedData;
|
||||
List->Reserved = read_uint32(&b);
|
||||
List->Version = read_uint32(&b);
|
||||
memcpy(List->MagicNumber, b.Buffer, 4);
|
||||
skipbytes(&b, 4);
|
||||
List->ConstantCount = read_uint32(&b);
|
||||
if(List->Reserved != 0 || List->Version == 0 || List->Version > 2)
|
||||
return 0;
|
||||
|
||||
List->Constants = calloc(List->ConstantCount, sizeof(IFFConstant));
|
||||
if(List->Constants == NULL)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<List->ConstantCount; i++){
|
||||
IFFConstant * Constant = &List->Constants[i];
|
||||
unsigned s;
|
||||
for(s=0; s<2; s++){
|
||||
char ** string = (s==0) ? &Constant->Name : &Constant->Description;
|
||||
if(List->Version < 2){
|
||||
/* C string, possible padding */
|
||||
if(!read_c_string(&b, string))
|
||||
return 0;
|
||||
|
||||
/* Skip past the 0xA3 character;
|
||||
** see global.iff chunk 546 for why you can't do modulo-2 to detect this */
|
||||
if(b.Size && *b.Buffer == 0xA3)
|
||||
skipbytes(&b, 1);
|
||||
}else{
|
||||
/* Extended Pascal string, no padding */
|
||||
if(!read_pascal2_string(&b, string))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(s == 0){
|
||||
if(b.Size < 4) return 0;
|
||||
Constant->Value = read_float(&b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_fcns(void * FormattedData){
|
||||
IFFConstantList * List = FormattedData;
|
||||
if(List->Constants){
|
||||
unsigned c;
|
||||
for(c=0; c<List->ConstantCount; c++){
|
||||
free(List->Constants[c].Name);
|
||||
free(List->Constants[c].Description);
|
||||
}
|
||||
free(List->Constants);
|
||||
}
|
||||
}
|
28
library/formats/iff/glob.c
Normal file
28
library/formats/iff/glob.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
glob.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_glob(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
bytestream b;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
|
||||
/* Try reading as a C string, and if that fails, again as a Pascal string */
|
||||
return (read_c_string(&b, (char**) &ChunkInfo->FormattedData) ||
|
||||
read_pascal_string(&b, (char**) &ChunkInfo->FormattedData));
|
||||
}
|
251
library/formats/iff/iff.c
Normal file
251
library/formats/iff/iff.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
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>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
/****
|
||||
** Supported Chunks
|
||||
*/
|
||||
|
||||
#define iff_register(x) \
|
||||
int iff_parse_##x(IFFChunk *, const uint8_t *); \
|
||||
void iff_free_##x(void *)
|
||||
|
||||
iff_register(bcon);
|
||||
iff_register(dgrp);
|
||||
iff_register(str);
|
||||
iff_register(cats);
|
||||
iff_register(c_string);
|
||||
iff_register(glob);
|
||||
iff_register(fcns);
|
||||
iff_register(palt);
|
||||
iff_register(bhav);
|
||||
iff_register(objf);
|
||||
iff_register(spr);
|
||||
iff_register(spr2);
|
||||
iff_register(tmpl);
|
||||
iff_register(trcn);
|
||||
iff_register(rsmp);
|
||||
|
||||
/* The ordering of these chunk types must match throughout this block: */
|
||||
const char chunktypes[] =
|
||||
"STR#" "CTSS" "FAMs" "TTAs" "CST\0"
|
||||
"CATS"
|
||||
"FWAV"
|
||||
"GLOB"
|
||||
"BCON"
|
||||
"FCNS"
|
||||
"PALT"
|
||||
"SPR#"
|
||||
"SPR2"
|
||||
"DGRP"
|
||||
"TMPL"
|
||||
"TRCN"
|
||||
"BHAV"
|
||||
"OBJf"
|
||||
"rsmp"
|
||||
;
|
||||
int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
|
||||
iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str,
|
||||
iff_parse_cats,
|
||||
iff_parse_c_string,
|
||||
iff_parse_glob,
|
||||
iff_parse_bcon,
|
||||
iff_parse_fcns,
|
||||
iff_parse_palt,
|
||||
iff_parse_spr,
|
||||
iff_parse_spr2,
|
||||
iff_parse_dgrp,
|
||||
iff_parse_tmpl,
|
||||
iff_parse_trcn,
|
||||
iff_parse_bhav,
|
||||
iff_parse_objf,
|
||||
iff_parse_rsmp
|
||||
};
|
||||
void (* const iff_free_function[])(void*) = {
|
||||
iff_free_str, iff_free_str, iff_free_str, iff_free_str, iff_free_str,
|
||||
iff_free_cats,
|
||||
NULL,
|
||||
NULL,
|
||||
iff_free_bcon,
|
||||
iff_free_fcns,
|
||||
NULL,
|
||||
iff_free_spr,
|
||||
iff_free_spr,
|
||||
iff_free_dgrp,
|
||||
iff_free_tmpl,
|
||||
iff_free_trcn,
|
||||
iff_free_bhav,
|
||||
iff_free_objf,
|
||||
iff_free_rsmp
|
||||
};
|
||||
/* End */
|
||||
|
||||
|
||||
/****
|
||||
** API public functions
|
||||
*/
|
||||
|
||||
int iff_create(IFFFile * IFFFileInfo)
|
||||
{
|
||||
memset(IFFFileInfo, 0, sizeof(IFFFile));
|
||||
|
||||
IFFFileInfo->Chunks = calloc(1, sizeof(IFFChunk));
|
||||
if(IFFFileInfo->Chunks == NULL)
|
||||
return 0;
|
||||
IFFFileInfo->SizeAllocated = sizeof(IFFChunk);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
IFFChunk * iff_add_chunk(IFFFile * IFFFileInfo)
|
||||
{
|
||||
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;
|
||||
|
||||
IFFFileInfo->Chunks = ptr;
|
||||
IFFFileInfo->SizeAllocated<<=1;
|
||||
}
|
||||
|
||||
return &IFFFileInfo->Chunks[IFFFileInfo->ChunkCount++];
|
||||
}
|
||||
|
||||
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);
|
||||
ChunkInfo->Type[4] = 0x00;
|
||||
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;
|
||||
|
||||
ChunkInfo->Size -= 76;
|
||||
|
||||
if(ChunkInfo->Size){
|
||||
ChunkInfo->Data = malloc(ChunkInfo->Size);
|
||||
if(ChunkInfo->Data == NULL)
|
||||
return 0;
|
||||
memcpy(ChunkInfo->Data, Buffer+76, ChunkInfo->Size);
|
||||
}
|
||||
ChunkInfo->FormattedData = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize)
|
||||
{
|
||||
while(BufferSize){
|
||||
IFFChunk * chunk = iff_add_chunk(IFFFileInfo);
|
||||
if(chunk == NULL)
|
||||
return 0;
|
||||
if(!iff_read_chunk(chunk, Buffer, BufferSize))
|
||||
return 0;
|
||||
|
||||
Buffer += chunk->Size + 76;
|
||||
BufferSize -= chunk->Size + 76;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
iff_free_chunk(ChunkInfo);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void iff_free_chunk(IFFChunk * ChunkInfo){
|
||||
unsigned i;
|
||||
if(ChunkInfo == NULL || ChunkInfo->FormattedData == NULL) return;
|
||||
|
||||
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);
|
||||
ChunkInfo->FormattedData = NULL;
|
||||
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);
|
||||
}
|
||||
}
|
365
library/formats/iff/iff.h
Normal file
365
library/formats/iff/iff.h
Normal file
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
iff.h - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef IFF_H
|
||||
#define IFF_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef read_uint32be
|
||||
#define read_int32be(x) (signed)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0)))
|
||||
#define read_int24be(x) (signed)(((x)[0]<<(8*2)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*0)))
|
||||
#define read_int16be(x) (signed)(((x)[0]<<(8*1)) | ((x)[1]<<(8*0)))
|
||||
#define read_int8be(x) (signed)(((x)[0]<<(8*0)))
|
||||
#define read_int32le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
|
||||
#define read_int24le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)))
|
||||
#define read_int16le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
|
||||
#define read_int8le(x) (signed)(((x)[0]<<(8*0)))
|
||||
#define read_uint32be(x) (unsigned)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0)))
|
||||
#define read_uint24be(x) (unsigned)(((x)[0]<<(8*2)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*0)))
|
||||
#define read_uint16be(x) (unsigned)(((x)[0]<<(8*1)) | ((x)[1]<<(8*0)))
|
||||
#define read_uint8be(x) (unsigned)(((x)[0]<<(8*0)))
|
||||
#define read_uint32le(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
|
||||
#define read_uint24le(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)))
|
||||
#define read_uint16le(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
|
||||
#define read_uint8le(x) (unsigned)(((x)[0]<<(8*0)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** IFF file structs
|
||||
*/
|
||||
|
||||
typedef struct IFFChunk_s
|
||||
{
|
||||
char Type[5];
|
||||
uint32_t Size; /* After subtracting the 76-byte header */
|
||||
uint16_t ChunkID;
|
||||
uint16_t Flags;
|
||||
char Label[65];
|
||||
uint8_t * Data;
|
||||
void * FormattedData;
|
||||
} IFFChunk;
|
||||
|
||||
typedef struct IFFFile_s
|
||||
{
|
||||
uint8_t Header[64];
|
||||
|
||||
uint32_t ChunkCount;
|
||||
size_t SizeAllocated;
|
||||
IFFChunk * Chunks;
|
||||
IFFChunk * ResourceMap;
|
||||
} IFFFile;
|
||||
|
||||
static const uint8_t Header_IFF[] = "IFF FILE 2.5:TYPE FOLLOWED BY SIZE\0 JAMIE DOORNBOS & MAXIS 1";
|
||||
|
||||
/*
|
||||
** IFF chunk structs
|
||||
*/
|
||||
|
||||
/* BCON chunk */
|
||||
|
||||
typedef struct IFF_BCON_s
|
||||
{
|
||||
uint8_t ConstantCount;
|
||||
uint8_t Flags;
|
||||
uint16_t * Constants;
|
||||
} IFF_BCON;
|
||||
|
||||
/* BHAV chunk */
|
||||
|
||||
typedef struct IFFInstruction_s
|
||||
{
|
||||
uint16_t Opcode;
|
||||
uint8_t TDest;
|
||||
uint8_t FDest;
|
||||
uint8_t Operands[8];
|
||||
} IFFInstruction;
|
||||
|
||||
typedef struct IFFBehavior_s
|
||||
{
|
||||
uint16_t Version;
|
||||
uint32_t InstructionCount;
|
||||
uint8_t Type;
|
||||
uint8_t ArgumentCount;
|
||||
uint16_t LocalCount;
|
||||
uint16_t Flags;
|
||||
IFFInstruction * Instructions;
|
||||
} IFFBehavior;
|
||||
|
||||
/* DGRP chunk */
|
||||
|
||||
typedef struct IFFSpriteInfo_s
|
||||
{
|
||||
uint16_t Type;
|
||||
uint32_t ChunkID;
|
||||
uint32_t SpriteIndex;
|
||||
uint16_t Flags;
|
||||
int32_t SpriteX;
|
||||
int32_t SpriteY;
|
||||
float ObjectZ;
|
||||
float ObjectX;
|
||||
float ObjectY;
|
||||
} IFFSpriteInfo;
|
||||
|
||||
typedef struct IFFDrawAngle_s
|
||||
{
|
||||
uint16_t SpriteCount;
|
||||
uint32_t Direction;
|
||||
uint32_t Zoom;
|
||||
IFFSpriteInfo * SpriteInfo;
|
||||
} IFFDrawAngle;
|
||||
|
||||
typedef struct IFFDrawGroup_s
|
||||
{
|
||||
uint16_t Version;
|
||||
uint32_t AngleCount;
|
||||
IFFDrawAngle DrawAngles[12];
|
||||
} IFFDrawGroup;
|
||||
|
||||
enum IFFDrawDirection {
|
||||
IFFDIRECTION_NORTHEAST = 1,
|
||||
IFFDIRECTION_SOUTHEAST = 4,
|
||||
IFFDIRECTION_NORTHWEST = 16,
|
||||
IFFDIRECTION_SOUTHWEST = 64
|
||||
};
|
||||
|
||||
enum IFFDrawZoom {
|
||||
IFFZOOM_FAR = 1,
|
||||
IFFZOOM_MIDDLE,
|
||||
IFFZOOM_CLOSE
|
||||
};
|
||||
|
||||
/* FCNS chunk */
|
||||
|
||||
typedef struct IFFConstant_s
|
||||
{
|
||||
char * Name;
|
||||
float Value;
|
||||
char * Description;
|
||||
} IFFConstant;
|
||||
|
||||
typedef struct IFFConstantList_s
|
||||
{
|
||||
uint32_t Reserved;
|
||||
uint32_t Version;
|
||||
char MagicNumber[5];
|
||||
uint32_t ConstantCount;
|
||||
IFFConstant * Constants;
|
||||
} IFFConstantList;
|
||||
|
||||
/* OBJf chunk */
|
||||
|
||||
typedef struct IFFFunction_s
|
||||
{
|
||||
uint16_t ConditionID;
|
||||
uint16_t ActionID;
|
||||
} IFFFunction;
|
||||
|
||||
typedef struct IFFFunctionTable_s
|
||||
{
|
||||
uint32_t Reserved;
|
||||
uint32_t Version;
|
||||
char MagicNumber[5];
|
||||
uint32_t FunctionCount;
|
||||
IFFFunction * Functions;
|
||||
} IFFFunctionTable;
|
||||
|
||||
/* PALT chunk */
|
||||
|
||||
typedef struct IFFPalette_s
|
||||
{
|
||||
uint32_t Version;
|
||||
uint32_t ColorCount;
|
||||
uint32_t Reserved1;
|
||||
uint32_t Reserved2;
|
||||
uint8_t Data[256*3];
|
||||
} IFFPalette;
|
||||
|
||||
/* SPR#/SPR2 chunk */
|
||||
|
||||
typedef struct IFFSprite_s
|
||||
{
|
||||
uint32_t Reserved;
|
||||
uint16_t Height;
|
||||
uint16_t Width;
|
||||
uint32_t Flags;
|
||||
uint16_t PaletteID;
|
||||
uint16_t TransparentColor;
|
||||
int16_t YLoc;
|
||||
int16_t XLoc;
|
||||
uint8_t * IndexData;
|
||||
uint8_t * BGRA32Data;
|
||||
uint8_t * ZBuffer;
|
||||
|
||||
uint8_t InvalidDimensions;
|
||||
} IFFSprite;
|
||||
|
||||
typedef struct IFFSpriteList_s
|
||||
{
|
||||
uint32_t Version;
|
||||
uint32_t SpriteCount;
|
||||
uint32_t PaletteID;
|
||||
IFFSprite * Sprites;
|
||||
} IFFSpriteList;
|
||||
|
||||
enum IFFSpriteFlags {
|
||||
IFFSPRITE_FLAG_COLOR = 1,
|
||||
IFFSPRITE_FLAG_ZBUFFER = 2,
|
||||
IFFSPRITE_FLAG_ALPHA = 4
|
||||
};
|
||||
|
||||
int iff_depalette(IFFSprite * Sprite, const IFFPalette * Palette);
|
||||
|
||||
/* STR# chunk */
|
||||
|
||||
enum IFFLanguage {
|
||||
IFFLANG_DEFAULT = 0,
|
||||
IFFLANG_EN_US = 1,
|
||||
IFFLANG_EN_INTERNATIONAL = 2,
|
||||
IFFLANG_FRENCH = 3,
|
||||
IFFLANG_GERMAN = 4,
|
||||
IFFLANG_ITALIAN = 5,
|
||||
IFFLANG_SPANISH = 6,
|
||||
IFFLANG_DUTCH = 7,
|
||||
IFFLANG_DANISH = 8,
|
||||
IFFLANG_SWEDISH = 9,
|
||||
IFFLANG_NORWEGIAN = 10,
|
||||
IFFLANG_FINNISH = 11,
|
||||
IFFLANG_HEBREW = 12,
|
||||
IFFLANG_RUSSIAN = 13,
|
||||
IFFLANG_PORTUGUESE = 14,
|
||||
IFFLANG_JAPANESE = 15,
|
||||
IFFLANG_POLISH = 16,
|
||||
IFFLANG_CHINESE_SIMPLIFIED = 17,
|
||||
IFFLANG_CHINESE_TRADITIONAL = 18,
|
||||
IFFLANG_THAI = 19,
|
||||
IFFLANG_KOREAN = 20
|
||||
};
|
||||
|
||||
typedef struct IFFStringPair_s
|
||||
{
|
||||
uint8_t LanguageSet;
|
||||
char * Key;
|
||||
char * Value;
|
||||
} IFFStringPair;
|
||||
|
||||
typedef struct IFFLanguageSet_s
|
||||
{
|
||||
uint16_t PairCount;
|
||||
IFFStringPair * Pairs;
|
||||
} IFFLanguageSet;
|
||||
|
||||
typedef struct IFF_STR_s
|
||||
{
|
||||
int16_t Format;
|
||||
IFFLanguageSet LanguageSets[20];
|
||||
} IFFString;
|
||||
|
||||
/* TMPL chunk */
|
||||
|
||||
typedef struct IFFTemplateField_s
|
||||
{
|
||||
char * Name;
|
||||
char Type[5];
|
||||
} IFFTemplateField;
|
||||
|
||||
typedef struct IFFTemplate_s
|
||||
{
|
||||
uint32_t FieldCount;
|
||||
IFFTemplateField * Fields;
|
||||
} IFFTemplate;
|
||||
|
||||
/* TRCN chunk */
|
||||
|
||||
typedef struct IFFRangeEntry_s
|
||||
{
|
||||
uint32_t IsUsed;
|
||||
uint32_t DefaultValue;
|
||||
char * Name;
|
||||
char * Comment;
|
||||
uint8_t Enforced;
|
||||
uint16_t RangeMin;
|
||||
uint16_t RangeMax;
|
||||
} IFFRangeEntry;
|
||||
|
||||
typedef struct IFFRangeSet_s
|
||||
{
|
||||
uint32_t Reserved;
|
||||
uint32_t Version;
|
||||
char MagicNumber[5];
|
||||
uint32_t RangeCount;
|
||||
IFFRangeEntry * Ranges;
|
||||
} IFFRangeSet;
|
||||
|
||||
/* rsmp chunk */
|
||||
|
||||
typedef struct IFFResource_s
|
||||
{
|
||||
uint32_t Offset;
|
||||
uint32_t ChunkID;
|
||||
uint16_t Flags;
|
||||
char * Label;
|
||||
} IFFResource;
|
||||
|
||||
typedef struct IFFResouceType_s
|
||||
{
|
||||
char Type[5];
|
||||
uint32_t ResourceCount;
|
||||
IFFResource * Resources;
|
||||
} IFFResourceType;
|
||||
|
||||
typedef struct IFFResourceMap_s
|
||||
{
|
||||
uint32_t Reserved;
|
||||
uint32_t Version;
|
||||
char MagicNumber[5];
|
||||
uint32_t IFFSize;
|
||||
uint32_t TypeCount;
|
||||
IFFResourceType * ResourceTypes;
|
||||
} IFFResourceMap;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** IFF file functions
|
||||
*/
|
||||
|
||||
int iff_create(IFFFile * IFFFileInfo);
|
||||
int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize);
|
||||
|
||||
IFFChunk * iff_add_chunk(IFFFile * IFFFileInfo);
|
||||
int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize);
|
||||
int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer);
|
||||
int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize);
|
||||
IFFChunk * iff_find_chunk(IFFFile * IFFFileInfo, const char * Type, int ChunkID);
|
||||
|
||||
void iff_free_chunk(IFFChunk * ChunkInfo);
|
||||
void iff_delete_chunk(IFFFile * IFFFileInfo, int Position);
|
||||
void iff_delete(IFFFile * IFFFileInfo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
173
library/formats/iff/iffexport.c
Normal file
173
library/formats/iff/iffexport.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
iffexport.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include "iff.h"
|
||||
|
||||
static FILE * hFile = NULL;
|
||||
static uint8_t * IFFData = NULL;
|
||||
static IFFFile IFFFileInfo;
|
||||
static int iffcreated = 0;
|
||||
|
||||
static void Shutdown_M(const char * Message){
|
||||
fprintf(stderr, "iffexport: error: %s.\n", Message);
|
||||
if(iffcreated)
|
||||
iff_delete(&IFFFileInfo);
|
||||
free(IFFData);
|
||||
if(hFile)
|
||||
fclose(hFile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int charmatches(char c, const char * filter){
|
||||
while(*filter){
|
||||
if(c == *filter) return 1;
|
||||
filter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int overwrite = 0;
|
||||
const char *InFile, *OutDirectory;
|
||||
size_t FileSize;
|
||||
clock_t BeginningTime;
|
||||
unsigned chunkcount, chunk;
|
||||
unsigned exported = 0;
|
||||
IFFChunk * ChunkData;
|
||||
|
||||
if(argc < 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
|
||||
printf("Usage: iffexport [-f] infile outdirectory\n"
|
||||
"Export the resources of an EA IFF file.\n"
|
||||
"Use -f to force overwriting without confirmation.\n"
|
||||
"\n"
|
||||
"Report bugs to <X-Fi6@phppoll.org>.\n"
|
||||
"iffexport is maintained by the Niotso project.\n"
|
||||
"Home page: <http://www.niotso.org/>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc >= 4 && !strcmp(argv[1], "-f")){
|
||||
overwrite++;
|
||||
InFile = argv[2];
|
||||
OutDirectory = argv[3];
|
||||
}else{
|
||||
InFile = argv[1];
|
||||
OutDirectory = argv[2];
|
||||
}
|
||||
|
||||
/****
|
||||
** Open the file and read in entire contents to memory
|
||||
*/
|
||||
|
||||
hFile = fopen(InFile, "rb");
|
||||
if(hFile == NULL)
|
||||
Shutdown_M("The specified input file does not exist or could not be opened for reading");
|
||||
fseek(hFile, 0, SEEK_END);
|
||||
FileSize = ftell(hFile);
|
||||
if(FileSize < 24)
|
||||
Shutdown_M("Not a valid IFF file");
|
||||
fseek(hFile, 0, SEEK_SET);
|
||||
|
||||
IFFData = malloc(FileSize);
|
||||
if(IFFData == NULL)
|
||||
Shutdown_M("Memory for this file could not be allocated");
|
||||
if(fread(IFFData, 1, FileSize, hFile) != FileSize)
|
||||
Shutdown_M("The input file could not be read");
|
||||
fclose(hFile); hFile = NULL;
|
||||
|
||||
/****
|
||||
** Load header information
|
||||
*/
|
||||
|
||||
if(!iff_create(&IFFFileInfo))
|
||||
Shutdown_M("Memory for this file could not be allocated");
|
||||
iffcreated++;
|
||||
if(!iff_read_header(&IFFFileInfo, IFFData, FileSize))
|
||||
Shutdown_M("Not a valid IFF file");
|
||||
|
||||
/****
|
||||
** Load entry information
|
||||
*/
|
||||
|
||||
if(!iff_enumerate_chunks(&IFFFileInfo, IFFData+64, FileSize-64))
|
||||
Shutdown_M("Chunk data is corrupt");
|
||||
|
||||
free(IFFData); IFFData = NULL;
|
||||
|
||||
chunkcount = IFFFileInfo.ChunkCount;
|
||||
printf("This IFF file contains %u chunks.\n\nExporting\n", chunkcount);
|
||||
BeginningTime = clock();
|
||||
|
||||
/****
|
||||
** Extract each entry
|
||||
*/
|
||||
for(chunk = 1, ChunkData = IFFFileInfo.Chunks; chunk <= chunkcount; chunk++, ChunkData++){
|
||||
char name[256], destination[256];
|
||||
char filter[] = "\\/:*?\"<>|";
|
||||
int i;
|
||||
|
||||
sprintf(name, "%03u-%s-%04X-%s", chunk, ChunkData->Type, ChunkData->ChunkID, ChunkData->Label);
|
||||
for(i=0; name[i] != 0x00; i++){
|
||||
if(name[i] == '\t') name[i] = ' ';
|
||||
else if(name[i] < ' ' || name[i] > '~') name[i] = '.';
|
||||
else if(charmatches(name[i], "\\/:*?\"<>|")) name[i] = '.';
|
||||
}
|
||||
for(i=0; i<9; i++){
|
||||
char * c = name;
|
||||
while((c = strchr(c, filter[i])) != NULL)
|
||||
*c = '.';
|
||||
}
|
||||
sprintf(destination, "%s/%s.%s", OutDirectory, name,
|
||||
(!memcmp(ChunkData->Type, "BMP_", 4) || !memcmp(ChunkData->Type, "FBMP", 4)) ? "bmp" : "dat");
|
||||
|
||||
if(!overwrite){
|
||||
hFile = fopen(destination, "rb");
|
||||
if(hFile != NULL){
|
||||
/* File exists */
|
||||
char c;
|
||||
fclose(hFile); hFile = NULL;
|
||||
printf("File \"%s\" exists.\nContinue anyway? (y/n) ", destination);
|
||||
c = getchar();
|
||||
if(c != 'y' && c != 'Y'){
|
||||
printf("\n");
|
||||
Shutdown_M("Aborted");
|
||||
}
|
||||
}
|
||||
overwrite++;
|
||||
}
|
||||
hFile = fopen(destination, "wb");
|
||||
if(hFile == NULL)
|
||||
Shutdown_M("The output file could not be opened for writing");
|
||||
fwrite(ChunkData->Data, 1, ChunkData->Size, hFile);
|
||||
fclose(hFile);
|
||||
|
||||
exported++;
|
||||
}
|
||||
|
||||
printf("\nExported %u of %u chunks in %.2f seconds.", exported, chunkcount,
|
||||
((float) (clock() - BeginningTime))/CLOCKS_PER_SEC);
|
||||
|
||||
iff_delete(&IFFFileInfo);
|
||||
|
||||
return 0;
|
||||
}
|
146
library/formats/iff/iffparser.h
Normal file
146
library/formats/iff/iffparser.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
iffparser.h - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iff.h"
|
||||
|
||||
typedef struct {
|
||||
const uint8_t * Buffer;
|
||||
size_t Size;
|
||||
const uint8_t * StartPos;
|
||||
size_t TotalSize;
|
||||
uint8_t Endian; /* 0 = little, 1 = big */
|
||||
} bytestream;
|
||||
|
||||
static __inline void set_bytestream(bytestream * b, const uint8_t * Buffer, size_t Size){
|
||||
b->Buffer = Buffer;
|
||||
b->Size = Size;
|
||||
b->StartPos = Buffer;
|
||||
b->TotalSize = Size;
|
||||
b->Endian = 0;
|
||||
}
|
||||
|
||||
static __inline uint32_t read_uint32(bytestream * b){
|
||||
unsigned value = (b->Endian == 0) ? read_uint32le(b->Buffer) : read_uint32be(b->Buffer);
|
||||
b->Buffer += 4;
|
||||
b->Size -= 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
static __inline uint16_t read_uint16(bytestream * b){
|
||||
unsigned value = (b->Endian == 0) ? read_uint16le(b->Buffer) : read_uint16be(b->Buffer);
|
||||
b->Buffer += 2;
|
||||
b->Size -= 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
static __inline uint8_t read_uint8(bytestream * b){
|
||||
uint8_t value = b->Buffer[0];
|
||||
b->Buffer += 1;
|
||||
b->Size -= 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
static __inline float read_float(bytestream *b){
|
||||
union { float f; uint32_t v; } value;
|
||||
value.v = read_uint32(b);
|
||||
return value.f;
|
||||
}
|
||||
|
||||
static __inline int skipbytes(bytestream * b, size_t bytes){
|
||||
if(b->Size < bytes) return 0;
|
||||
b->Buffer += bytes; b->Size -= bytes;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __inline int seekto(bytestream * b, size_t Position){
|
||||
if(Position > b->TotalSize) return 0;
|
||||
b->Buffer = b->StartPos + Position;
|
||||
b->Size = b->TotalSize - Position;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __inline size_t read_c_string(bytestream * b, char ** dest){
|
||||
size_t length;
|
||||
for(length=0; length != b->Size && b->Buffer[length]; length++);
|
||||
if(length == b->Size) return 0;
|
||||
|
||||
if(length != 0){
|
||||
*dest = malloc(length+1);
|
||||
if(*dest == NULL) return 0;
|
||||
strcpy(*dest, (char*) b->Buffer);
|
||||
}
|
||||
|
||||
b->Buffer += length + 1;
|
||||
b->Size -= length + 1;
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
static __inline size_t read_pascal_string(bytestream * b, char ** dest){
|
||||
size_t length;
|
||||
if(!b->Size) return 0;
|
||||
length = b->Buffer[0];
|
||||
if(length >= b->Size) return 0;
|
||||
|
||||
if(length > 0){
|
||||
*dest = malloc(length+1);
|
||||
if(*dest == NULL) return 0;
|
||||
memcpy(*dest, b->Buffer+1, length);
|
||||
(*dest)[length] = 0x00;
|
||||
}
|
||||
|
||||
b->Buffer += 1 + length;
|
||||
b->Size -= 1 + length;
|
||||
return 1 + length;
|
||||
}
|
||||
|
||||
static __inline size_t read_pascal2_string(bytestream * b, char ** dest){
|
||||
size_t length;
|
||||
int countbytes = 1;
|
||||
if(!b->Size) return 0;
|
||||
length = b->Buffer[0];
|
||||
|
||||
if(length > 127){
|
||||
/* 2-byte length */
|
||||
if(b->Size == 1) return 0;
|
||||
length = (length&127) | (b->Buffer[1]<<7);
|
||||
countbytes++;
|
||||
}
|
||||
|
||||
if(countbytes+length > b->Size) return 0;
|
||||
|
||||
if(length != 0){
|
||||
*dest = malloc(length+1);
|
||||
if(*dest == NULL) return 0;
|
||||
memcpy(*dest, b->Buffer+countbytes, length);
|
||||
(*dest)[length] = 0x00;
|
||||
}
|
||||
|
||||
b->Buffer += countbytes + length;
|
||||
b->Size -= countbytes + length;
|
||||
return countbytes + length;
|
||||
}
|
||||
|
||||
static __inline size_t skip_padding(bytestream * b){
|
||||
size_t padding = 0;
|
||||
while(b->Size && b->Buffer[0] == 0xA3){
|
||||
padding++;
|
||||
b->Buffer++;
|
||||
b->Size--;
|
||||
}
|
||||
return padding;
|
||||
}
|
60
library/formats/iff/objf.c
Normal file
60
library/formats/iff/objf.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
objf.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
|
||||
Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_objf(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFFunctionTable *Table;
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 16)
|
||||
return 0;
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFFunctionTable));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
Table = ChunkInfo->FormattedData;
|
||||
Table->Reserved = read_uint32le(Buffer);
|
||||
Table->Version = read_uint32le(Buffer+4);
|
||||
memcpy(Table->MagicNumber, Buffer+8, 4);
|
||||
Table->MagicNumber[4] = 0x00;
|
||||
Table->FunctionCount = read_uint32le(Buffer+12);
|
||||
if(Table->Reserved != 0 || Table->Version != 0)
|
||||
return 0;
|
||||
if(Table->FunctionCount == 0)
|
||||
return 1;
|
||||
if(Table->FunctionCount > (ChunkInfo->Size - 16)/4)
|
||||
return 0;
|
||||
|
||||
Table->Functions = malloc(Table->FunctionCount * sizeof(IFFFunction));
|
||||
if(Table->Functions == NULL)
|
||||
return 0;
|
||||
|
||||
Buffer += 16;
|
||||
for(i=0; i<Table->FunctionCount; i++, Buffer += 4){
|
||||
Table->Functions[i].ConditionID = read_uint16le(Buffer);
|
||||
Table->Functions[i].ActionID = read_uint16le(Buffer+2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_objf(void * FormattedData){
|
||||
IFFFunctionTable *Table = FormattedData;
|
||||
free(Table->Functions);
|
||||
}
|
41
library/formats/iff/palt.c
Normal file
41
library/formats/iff/palt.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
palt.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_palt(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFPalette *Palette;
|
||||
|
||||
if(ChunkInfo->Size < 16)
|
||||
return 0;
|
||||
ChunkInfo->FormattedData = malloc(sizeof(IFFPalette));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
Palette = ChunkInfo->FormattedData;
|
||||
Palette->Version = read_uint32le(Buffer);
|
||||
Palette->ColorCount = read_uint32le(Buffer+4);
|
||||
Palette->Reserved1 = read_uint32le(Buffer+8);
|
||||
Palette->Reserved2 = read_uint32le(Buffer+12);
|
||||
if(Palette->Version != 1 || Palette->ColorCount == 0 || Palette->ColorCount > 256 ||
|
||||
Palette->Reserved1 != 0 || Palette->Reserved2 != 0 || Palette->ColorCount*3 > ChunkInfo->Size-16)
|
||||
return 0;
|
||||
|
||||
memcpy(Palette->Data, Buffer+16, Palette->ColorCount*3);
|
||||
return 1;
|
||||
}
|
93
library/formats/iff/rsmp.c
Normal file
93
library/formats/iff/rsmp.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
rsmp.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFResourceMap *Map;
|
||||
bytestream b;
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 20)
|
||||
return 0;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFResourceMap));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
Map = ChunkInfo->FormattedData;
|
||||
Map->Reserved = read_uint32(&b);
|
||||
Map->Version = read_uint32(&b);
|
||||
memcpy(Map->MagicNumber, b.Buffer, 4);
|
||||
skipbytes(&b, 4);
|
||||
Map->IFFSize = read_uint32(&b);
|
||||
Map->TypeCount = read_uint32(&b);
|
||||
if(Map->Reserved != 0 || Map->Version > 1)
|
||||
return 0;
|
||||
|
||||
Map->ResourceTypes = calloc(Map->TypeCount, sizeof(IFFResourceType));
|
||||
if(Map->ResourceTypes == NULL)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<Map->TypeCount; i++){
|
||||
IFFResourceType * Type = &Map->ResourceTypes[i];
|
||||
unsigned j;
|
||||
if(b.Size < 8) return 0;
|
||||
|
||||
memcpy(Type->Type, b.Buffer, 4);
|
||||
skipbytes(&b, 4);
|
||||
Type->ResourceCount = read_uint32(&b);
|
||||
Type->Resources = calloc(Type->ResourceCount, sizeof(IFFResource));
|
||||
if(Type->Resources == NULL)
|
||||
return 0;
|
||||
|
||||
for(j=0; j<Type->ResourceCount; j++){
|
||||
IFFResource * Resource = &Type->Resources[j];
|
||||
if(b.Size < ((Map->Version == 0) ? 9 : 11)) return 0;
|
||||
Resource->Offset = read_uint32(&b);
|
||||
Resource->ChunkID = (Map->Version == 0) ? read_uint16(&b) : read_uint32(&b);
|
||||
Resource->Flags = read_uint16(&b);
|
||||
|
||||
if(Map->Version == 0){
|
||||
if(!read_c_string(&b, &Resource->Label))
|
||||
return 0;
|
||||
}else{
|
||||
if(!read_pascal_string(&b, &Resource->Label))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_rsmp(void * FormattedData){
|
||||
IFFResourceMap * Map = FormattedData;
|
||||
if(Map->ResourceTypes){
|
||||
unsigned t;
|
||||
for(t=0; t<Map->TypeCount; t++){
|
||||
IFFResourceType * Type = &Map->ResourceTypes[t];
|
||||
if(Type->Resources){
|
||||
unsigned r;
|
||||
for(r=0; r<Type->ResourceCount; r++)
|
||||
free(Type->Resources[r].Label);
|
||||
free(Type->Resources);
|
||||
}
|
||||
}
|
||||
free(Map->ResourceTypes);
|
||||
}
|
||||
}
|
221
library/formats/iff/spr.c
Normal file
221
library/formats/iff/spr.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
spr.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFSpriteList *SpriteList;
|
||||
bytestream b;
|
||||
unsigned NextSpriteOffset; /* Used for Version 1001 in place of the offset table */
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 12)
|
||||
return 0;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
if((Buffer[0]|Buffer[1]) == 0) b.Endian++; /* Big endian */
|
||||
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFSpriteList));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
SpriteList = ChunkInfo->FormattedData;
|
||||
SpriteList->Version = read_uint32(&b);
|
||||
SpriteList->SpriteCount = read_uint32(&b);
|
||||
SpriteList->PaletteID = read_uint32(&b);
|
||||
if(SpriteList->Version < 502 || (SpriteList->Version > 505 && SpriteList->Version != 1001))
|
||||
return 0;
|
||||
|
||||
if(SpriteList->Version != 1001){
|
||||
if(SpriteList->SpriteCount > b.Size/4)
|
||||
return 0;
|
||||
}else{
|
||||
/* Sprite count is blank in version 1001, so we must walk and count up the sprites ourselves;
|
||||
** this is easy with the sprite size field */
|
||||
for(SpriteList->SpriteCount = 0; b.Size >= 16; SpriteList->SpriteCount++){
|
||||
if(read_uint32(&b) != 1001 || !skipbytes(&b, read_uint32(&b)))
|
||||
return 0;
|
||||
}
|
||||
NextSpriteOffset = 16;
|
||||
}
|
||||
|
||||
if(SpriteList->SpriteCount == 0)
|
||||
return 1;
|
||||
SpriteList->Sprites = calloc(SpriteList->SpriteCount, sizeof(IFFSprite));
|
||||
if(SpriteList->Sprites == NULL)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<SpriteList->SpriteCount; i++){
|
||||
IFFSprite * Sprite = &SpriteList->Sprites[i];
|
||||
unsigned SpriteSize;
|
||||
unsigned row = 0;
|
||||
|
||||
if(SpriteList->Version != 1001){
|
||||
/* Jump to the next sprite using the offset table; this is mandatory */
|
||||
seekto(&b, 12 + 4*i);
|
||||
if(!seekto(&b, read_uint32(&b)) || b.Size < 8)
|
||||
return 0;
|
||||
SpriteSize = b.Size;
|
||||
}else{
|
||||
/* Jump to the next sprite using the sprite size field; this is mandatory */
|
||||
seekto(&b, NextSpriteOffset);
|
||||
SpriteSize = read_uint32(&b);
|
||||
NextSpriteOffset += SpriteSize + 8;
|
||||
}
|
||||
|
||||
Sprite->Reserved = read_uint32(&b);
|
||||
Sprite->Height = read_uint16(&b);
|
||||
Sprite->Width = read_uint16(&b);
|
||||
if(Sprite->Reserved != 0 || Sprite->Height == 0 || Sprite->Width == 0 || Sprite->Height > UINT_MAX/2/Sprite->Width){
|
||||
/* This happens in the third sprite of every SPR# chunk in sprites.iff */
|
||||
Sprite->InvalidDimensions = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
SpriteSize -= 8;
|
||||
|
||||
Sprite->IndexData = calloc(Sprite->Width*Sprite->Height, 2);
|
||||
if(Sprite->IndexData == NULL)
|
||||
return 0;
|
||||
|
||||
while(1){
|
||||
/****
|
||||
** Row command: valid commands are 0, 4, 5, 9, and 16
|
||||
*/
|
||||
|
||||
uint8_t RowCommand, RowCount;
|
||||
|
||||
if(SpriteSize < 2)
|
||||
return 0;
|
||||
RowCommand = *(b.Buffer++);
|
||||
RowCount = *(b.Buffer++);
|
||||
SpriteSize -= 2;
|
||||
|
||||
if(RowCommand == 0 || RowCommand == 16){
|
||||
/* Start marker */
|
||||
}else if(RowCommand == 4){
|
||||
/****
|
||||
** Pixel command: valid commands are 1, 2, and 3
|
||||
*/
|
||||
|
||||
unsigned pixel = 0;
|
||||
|
||||
if(row == Sprite->Height || RowCount < 2 || (RowCount -= 2) > SpriteSize || RowCount%2 != 0)
|
||||
return 0;
|
||||
SpriteSize -= RowCount;
|
||||
|
||||
while(RowCount){
|
||||
uint8_t PixelCommand, PixelCount;
|
||||
uint8_t * IndexData;
|
||||
if(RowCount < 2)
|
||||
return 0;
|
||||
|
||||
PixelCommand = *(b.Buffer++);
|
||||
PixelCount = *(b.Buffer++);
|
||||
RowCount -= 2;
|
||||
|
||||
if(PixelCount > Sprite->Width - pixel)
|
||||
return 0;
|
||||
|
||||
IndexData = Sprite->IndexData + (Sprite->Width*row + pixel)*2;
|
||||
pixel += PixelCount;
|
||||
|
||||
if(PixelCommand == 1){
|
||||
/* Leave next n pixels as transparent */
|
||||
}else if(PixelCommand == 2){
|
||||
/* Set next n pixels to shared palette index */
|
||||
|
||||
uint8_t PaletteIndex;
|
||||
if(RowCount < 2)
|
||||
return 0;
|
||||
|
||||
PaletteIndex = *(b.Buffer++);
|
||||
b.Buffer++; /* Padding byte */
|
||||
RowCount -= 2;
|
||||
|
||||
while(PixelCount--){
|
||||
*IndexData++ = PaletteIndex;
|
||||
*IndexData++ = 0xFF;
|
||||
}
|
||||
}else if(PixelCommand == 3){
|
||||
/* Set next n pixels to n palette indices */
|
||||
|
||||
int padding = PixelCount%2;
|
||||
if(PixelCount + padding > RowCount)
|
||||
return 0;
|
||||
RowCount -= PixelCount + padding;
|
||||
|
||||
while(PixelCount--){
|
||||
*IndexData++ = *(b.Buffer++);
|
||||
*IndexData++ = 0xFF;
|
||||
}
|
||||
if(padding) b.Buffer++; /* Padding byte */
|
||||
}else return 0;
|
||||
}
|
||||
row++;
|
||||
}else if(RowCommand == 5){
|
||||
/* End marker */
|
||||
break;
|
||||
}else if(RowCommand == 9){
|
||||
/* Leave rows as transparent */
|
||||
|
||||
if(RowCount > Sprite->Height - row)
|
||||
return 0;
|
||||
row += RowCount;
|
||||
}else return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_spr(void * FormattedData){
|
||||
IFFSpriteList *SpriteList = FormattedData;
|
||||
if(SpriteList->Sprites){
|
||||
unsigned s;
|
||||
for(s=0; s<SpriteList->SpriteCount; s++){
|
||||
IFFSprite *Sprite = &SpriteList->Sprites[s];
|
||||
free(Sprite->IndexData);
|
||||
free(Sprite->BGRA32Data);
|
||||
free(Sprite->ZBuffer);
|
||||
}
|
||||
free(SpriteList->Sprites);
|
||||
}
|
||||
}
|
||||
|
||||
int iff_depalette(IFFSprite * Sprite, const IFFPalette * Palette){
|
||||
unsigned PixelCount = Sprite->Width*Sprite->Height;
|
||||
unsigned i;
|
||||
|
||||
Sprite->BGRA32Data = malloc(PixelCount*4);
|
||||
if(Sprite->BGRA32Data == NULL) return 0;
|
||||
|
||||
for(i=0; i<PixelCount; i++){
|
||||
uint8_t Index = Sprite->IndexData[2*i + 0];
|
||||
if(Index >= Palette->ColorCount){
|
||||
free(Sprite->BGRA32Data);
|
||||
Sprite->BGRA32Data = NULL;
|
||||
return 0;
|
||||
}
|
||||
Sprite->BGRA32Data[4*i + 0] = Palette->Data[3*Index + 2];
|
||||
Sprite->BGRA32Data[4*i + 1] = Palette->Data[3*Index + 1];
|
||||
Sprite->BGRA32Data[4*i + 2] = Palette->Data[3*Index + 0];
|
||||
Sprite->BGRA32Data[4*i + 3] = Sprite->IndexData[2*i + 1];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
227
library/formats/iff/spr2.c
Normal file
227
library/formats/iff/spr2.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
spr2.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_spr2(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFSpriteList *SpriteList;
|
||||
bytestream b;
|
||||
unsigned NextSpriteOffset; /* Used for Version 1001 in place of the offset table */
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 12)
|
||||
return 0;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
if((Buffer[0]|Buffer[1]) == 0) b.Endian++; /* Big endian */
|
||||
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFSpriteList));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
SpriteList = ChunkInfo->FormattedData;
|
||||
SpriteList->Version = read_uint32(&b);
|
||||
if(SpriteList->Version != 1000 && SpriteList->Version != 1001)
|
||||
return 0;
|
||||
|
||||
if(SpriteList->Version == 1000){
|
||||
SpriteList->SpriteCount = read_uint32(&b);
|
||||
SpriteList->PaletteID = read_uint32(&b);
|
||||
if(SpriteList->SpriteCount > b.Size/4)
|
||||
return 0;
|
||||
}else{
|
||||
SpriteList->PaletteID = read_uint32(&b);
|
||||
skipbytes(&b, 4);
|
||||
|
||||
/* Sprite count is blank in version 1001, so we must walk and count up the sprites ourselves;
|
||||
** this is easy with the sprite size field */
|
||||
for(SpriteList->SpriteCount = 0; b.Size >= 24; SpriteList->SpriteCount++){
|
||||
if(read_uint32(&b) != 1001 || !skipbytes(&b, read_uint32(&b)))
|
||||
return 0;
|
||||
}
|
||||
NextSpriteOffset = 16;
|
||||
}
|
||||
|
||||
if(SpriteList->SpriteCount == 0)
|
||||
return 1;
|
||||
SpriteList->Sprites = calloc(SpriteList->SpriteCount, sizeof(IFFSprite));
|
||||
if(SpriteList->Sprites == NULL)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<SpriteList->SpriteCount; i++){
|
||||
IFFSprite * Sprite = &SpriteList->Sprites[i];
|
||||
unsigned SpriteSize;
|
||||
unsigned row = 0;
|
||||
int j;
|
||||
|
||||
if(SpriteList->Version != 1001){
|
||||
/* Jump to the next sprite using the offset table; this is mandatory */
|
||||
seekto(&b, 12 + 4*i);
|
||||
if(!seekto(&b, read_uint32(&b)) || b.Size < 16)
|
||||
return 0;
|
||||
SpriteSize = b.Size;
|
||||
}else{
|
||||
/* Jump to the next sprite using the sprite size field; this is mandatory */
|
||||
seekto(&b, NextSpriteOffset);
|
||||
SpriteSize = read_uint32(&b);
|
||||
NextSpriteOffset += SpriteSize + 8;
|
||||
}
|
||||
|
||||
Sprite->Width = read_uint16(&b);
|
||||
Sprite->Height = read_uint16(&b);
|
||||
Sprite->Flags = read_uint32(&b);
|
||||
Sprite->PaletteID = read_uint16(&b);
|
||||
Sprite->TransparentColor = read_uint16(&b);
|
||||
Sprite->YLoc = read_uint16(&b);
|
||||
Sprite->XLoc = read_uint16(&b);
|
||||
if((Sprite->Flags != 1 && Sprite->Flags != 3 && Sprite->Flags != 7) || Sprite->TransparentColor >= 256)
|
||||
return 0;
|
||||
if(Sprite->Height == 0 || Sprite->Width == 0 || Sprite->Height > UINT_MAX/2/Sprite->Width){
|
||||
/* This happens in the many chunks in 2personportal.spf */
|
||||
Sprite->InvalidDimensions = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
SpriteSize -= 16;
|
||||
|
||||
Sprite->IndexData = malloc(Sprite->Width*Sprite->Height*2);
|
||||
if(Sprite->IndexData == NULL)
|
||||
return 0;
|
||||
for(j=0; j<Sprite->Width*Sprite->Height; j++){
|
||||
Sprite->IndexData[2*j + 0] = Sprite->TransparentColor;
|
||||
Sprite->IndexData[2*j + 1] = 0x00;
|
||||
}
|
||||
|
||||
if(Sprite->Flags >= 3){ /* Has the Z-Buffer flag */
|
||||
Sprite->ZBuffer = malloc(Sprite->Width*Sprite->Height);
|
||||
if(Sprite->ZBuffer == NULL)
|
||||
return 0;
|
||||
memset(Sprite->ZBuffer, 0xFF, Sprite->Width*Sprite->Height);
|
||||
}
|
||||
|
||||
while(1){
|
||||
/****
|
||||
** Row command: valid commands are 0, 4, and 5
|
||||
*/
|
||||
|
||||
uint8_t RowCommand; /* 3 bits */
|
||||
uint16_t RowCount; /* 13 bits */
|
||||
|
||||
if(SpriteSize < 2)
|
||||
return 0;
|
||||
RowCount = read_uint16le(b.Buffer);
|
||||
RowCommand = RowCount >> 13;
|
||||
RowCount &= 0x1FFF;
|
||||
|
||||
b.Buffer += 2;
|
||||
SpriteSize -= 2;
|
||||
|
||||
if(RowCommand == 0){
|
||||
/****
|
||||
** Pixel command: valid commands are 1, 2, 3, and 6
|
||||
*/
|
||||
|
||||
unsigned pixel = 0;
|
||||
|
||||
if(row == Sprite->Height || RowCount < 2 || (RowCount -= 2) > SpriteSize || RowCount%2 != 0)
|
||||
return 0;
|
||||
SpriteSize -= RowCount;
|
||||
|
||||
while(RowCount){
|
||||
uint8_t PixelCommand; /* 3 bits */
|
||||
uint16_t PixelCount; /* 13 bits */
|
||||
uint8_t * IndexData, * ZBuffer;
|
||||
if(RowCount < 2)
|
||||
return 0;
|
||||
|
||||
PixelCount = read_uint16le(b.Buffer);
|
||||
PixelCommand = PixelCount >> 13;
|
||||
PixelCount &= 0x1FFF;
|
||||
|
||||
b.Buffer += 2;
|
||||
RowCount -= 2;
|
||||
|
||||
if(PixelCount > Sprite->Width - pixel)
|
||||
return 0;
|
||||
|
||||
IndexData = Sprite->IndexData + (Sprite->Width*row + pixel)*2;
|
||||
ZBuffer = Sprite->ZBuffer + (Sprite->Width*row + pixel)*1;
|
||||
pixel += PixelCount;
|
||||
|
||||
if(PixelCommand == 1){
|
||||
/* color+z-buffer: Set next n pixels to n palette indices */
|
||||
|
||||
if(Sprite->Flags < 3 || PixelCount*2 > RowCount)
|
||||
return 0;
|
||||
RowCount -= PixelCount*2;
|
||||
|
||||
while(PixelCount--){
|
||||
*ZBuffer++ = *(b.Buffer++);
|
||||
IndexData[0] = *(b.Buffer++);
|
||||
IndexData[1] = (IndexData[0] != Sprite->TransparentColor) ? 0xFF : 0x00;
|
||||
IndexData += 2;
|
||||
}
|
||||
}else if(PixelCommand == 2){
|
||||
/* color+z-buffer+alpha: Set next n pixels to n palette indices */
|
||||
|
||||
int padding = PixelCount%2;
|
||||
if(Sprite->Flags < 7 || PixelCount*3 + padding > RowCount)
|
||||
return 0;
|
||||
RowCount -= PixelCount*3 + padding;
|
||||
|
||||
while(PixelCount--){
|
||||
*ZBuffer++ = *(b.Buffer++);
|
||||
*IndexData++ = *(b.Buffer++);
|
||||
*IndexData++ = *(b.Buffer++);
|
||||
}
|
||||
if(padding) b.Buffer++; /* Padding byte */
|
||||
}else if(PixelCommand == 3){
|
||||
/* Leave next n pixels as transparent */
|
||||
}else if(PixelCommand == 6){
|
||||
/* color: Set next n pixels to n palette indices */
|
||||
|
||||
int padding = PixelCount%2;
|
||||
if(PixelCount + padding > RowCount)
|
||||
return 0;
|
||||
RowCount -= PixelCount + padding;
|
||||
|
||||
while(PixelCount--){
|
||||
IndexData[0] = *(b.Buffer++);
|
||||
IndexData[1] = (IndexData[0] != Sprite->TransparentColor) ? 0xFF : 0x00;
|
||||
if(Sprite->Flags >= 3)
|
||||
*ZBuffer++ = (IndexData[0] != Sprite->TransparentColor) ? 0x00 : 0xFF;
|
||||
IndexData += 2;
|
||||
}
|
||||
if(padding) b.Buffer++; /* Padding byte */
|
||||
} else return 0;
|
||||
}
|
||||
row++;
|
||||
}else if(RowCommand == 4){
|
||||
/* Leave rows as transparent */
|
||||
|
||||
if(RowCount > Sprite->Height - row)
|
||||
return 0;
|
||||
row += RowCount;
|
||||
}else if(RowCommand == 5){
|
||||
/* End marker */
|
||||
break;
|
||||
}else return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
159
library/formats/iff/str.c
Normal file
159
library/formats/iff/str.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
str.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFString * StringData;
|
||||
bytestream b;
|
||||
|
||||
if(ChunkInfo->Size < 2)
|
||||
return 0;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFString));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
StringData = ChunkInfo->FormattedData;
|
||||
StringData->Format = read_uint16(&b);
|
||||
if(b.Size < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */
|
||||
return 1;
|
||||
|
||||
if(StringData->Format < -4 || StringData->Format > 0){
|
||||
/* Seen often in The Sims 1's Behavior.iff */
|
||||
StringData->Format = 0;
|
||||
seekto(&b, 0);
|
||||
b.Endian++;
|
||||
}
|
||||
|
||||
if(StringData->Format != -3){
|
||||
unsigned LanguageSetCount = 1;
|
||||
unsigned ls;
|
||||
|
||||
if(StringData->Format == -4){
|
||||
LanguageSetCount = read_uint8(&b);
|
||||
if(LanguageSetCount > 20) return 0;
|
||||
}
|
||||
|
||||
for(ls=0; ls<LanguageSetCount; ls++){
|
||||
IFFLanguageSet * LanguageSet = &StringData->LanguageSets[ls];
|
||||
unsigned p;
|
||||
|
||||
if(b.Size < 2) return 0;
|
||||
LanguageSet->PairCount = read_uint16(&b);
|
||||
if(LanguageSet->PairCount == 0)
|
||||
continue;
|
||||
|
||||
LanguageSet->Pairs = calloc(LanguageSet->PairCount, sizeof(IFFStringPair));
|
||||
if(LanguageSet->Pairs == NULL)
|
||||
return 0;
|
||||
|
||||
for(p=0; p<LanguageSet->PairCount; p++){
|
||||
IFFStringPair * Pair = &LanguageSet->Pairs[p];
|
||||
if(StringData->Format == 0){
|
||||
if(!read_pascal_string(&b, &Pair->Key))
|
||||
return 0;
|
||||
}else if(StringData->Format >=-2){
|
||||
if(!read_c_string(&b, &Pair->Key))
|
||||
return 0;
|
||||
if(StringData->Format == -2 && !read_c_string(&b, &Pair->Value))
|
||||
return 0;
|
||||
}else{
|
||||
if(!b.Size || read_uint8(&b) != ls)
|
||||
return 0;
|
||||
if(!read_pascal2_string(&b, &Pair->Key) || !read_pascal2_string(&b, &Pair->Value))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* FD FF requires a lot of extra work -- and isn't even found in TSO */
|
||||
IFFLanguageSet * LanguageSet = StringData->LanguageSets;
|
||||
unsigned TotalPairCount;
|
||||
unsigned Index[20] = {0};
|
||||
unsigned i;
|
||||
|
||||
TotalPairCount = read_uint16(&b);
|
||||
if(TotalPairCount == 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
** Scan through the chunk to count up the number of pairs in each LanguageSet,
|
||||
** and then allocate exactly that much and fill in the data on the second pass
|
||||
*/
|
||||
|
||||
/* 1st pass */
|
||||
for(i=0; i<TotalPairCount; i++){
|
||||
unsigned lang, s;
|
||||
if(b.Size == 0) return 0;
|
||||
lang = read_uint8(&b) - 1;
|
||||
if(lang >= 20) return 0;
|
||||
LanguageSet[lang].PairCount++;
|
||||
|
||||
for(s=0; s<2; s++){
|
||||
unsigned length;
|
||||
for(length=0; length != b.Size && b.Buffer[length]; length++);
|
||||
if(length == b.Size) return 0;
|
||||
skipbytes(&b, length+1);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<20; i++){
|
||||
LanguageSet[i].Pairs = calloc(LanguageSet[i].PairCount, sizeof(IFFStringPair));
|
||||
if(LanguageSet[i].Pairs == NULL) return 0;
|
||||
}
|
||||
|
||||
/* 2nd pass */
|
||||
set_bytestream(&b, Buffer+4, ChunkInfo->Size-4);
|
||||
for(i=0; i<TotalPairCount; i++){
|
||||
IFFStringPair * Pair;
|
||||
unsigned lang;
|
||||
lang = read_uint8(&b) - 1;
|
||||
Pair = &LanguageSet[lang].Pairs[Index[lang]++];
|
||||
|
||||
if(!read_c_string(&b, &Pair->Key) || !read_c_string(&b, &Pair->Value))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_str(void * FormattedData){
|
||||
/*
|
||||
** Requirements:
|
||||
** - PairCount and Pairs must be initialized for all 20 LanguageSets
|
||||
** - If the Pairs pointer is nonzero, there must be PairCount initialized pairs in Pairs
|
||||
*/
|
||||
|
||||
IFFString * StringData = FormattedData;
|
||||
unsigned ls;
|
||||
|
||||
for(ls=0; ls<20; ls++){
|
||||
IFFLanguageSet * LanguageSet = &StringData->LanguageSets[ls];
|
||||
if(LanguageSet->Pairs){
|
||||
unsigned p;
|
||||
for(p=0; p<LanguageSet->PairCount; p++){
|
||||
free(LanguageSet->Pairs[p].Key);
|
||||
free(LanguageSet->Pairs[p].Value);
|
||||
}
|
||||
free(LanguageSet->Pairs);
|
||||
}
|
||||
}
|
||||
}
|
25
library/formats/iff/string.c
Normal file
25
library/formats/iff/string.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
string.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_c_string(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
bytestream b;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
return (read_c_string(&b, (char**) &ChunkInfo->FormattedData) != 0);
|
||||
}
|
70
library/formats/iff/tmpl.c
Normal file
70
library/formats/iff/tmpl.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
tmpl.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_tmpl(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFTemplate *Template;
|
||||
bytestream b;
|
||||
const uint8_t * ptr = Buffer;
|
||||
unsigned Size = ChunkInfo->Size;
|
||||
unsigned FieldCount;
|
||||
unsigned i;
|
||||
if(Size == 0) return 1;
|
||||
|
||||
/* Walk through a first-pass to find the total field count */
|
||||
for(FieldCount=0; Size; FieldCount++){
|
||||
unsigned length = *ptr;
|
||||
if(Size < 5 || length > Size-5)
|
||||
return 0;
|
||||
ptr += length+5; Size -= length+5;
|
||||
}
|
||||
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFTemplate));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
Template = ChunkInfo->FormattedData;
|
||||
Template->FieldCount = FieldCount;
|
||||
Template->Fields = calloc(FieldCount, sizeof(IFFTemplateField));
|
||||
if(Template->Fields == NULL)
|
||||
return 0;
|
||||
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
|
||||
for(i=0; i<FieldCount; i++){
|
||||
IFFTemplateField * Field = &Template->Fields[i];
|
||||
if(!read_pascal_string(&b, &Field->Name))
|
||||
return 0;
|
||||
|
||||
memcpy(Field->Type, b.Buffer, 4);
|
||||
skipbytes(&b, 4);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_tmpl(void * FormattedData){
|
||||
IFFTemplate * Template = FormattedData;
|
||||
if(Template->Fields){
|
||||
unsigned f;
|
||||
for(f=0; f<Template->FieldCount; f++)
|
||||
free(Template->Fields[f].Name);
|
||||
free(Template->Fields);
|
||||
}
|
||||
}
|
0
library/formats/iff/tprp.c
Normal file
0
library/formats/iff/tprp.c
Normal file
100
library/formats/iff/trcn.c
Normal file
100
library/formats/iff/trcn.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
trcn.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
|
||||
Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "iffparser.h"
|
||||
|
||||
int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||
IFFRangeSet *RangeSet;
|
||||
bytestream b;
|
||||
unsigned i;
|
||||
|
||||
if(ChunkInfo->Size < 16)
|
||||
return 0;
|
||||
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFRangeSet));
|
||||
if(ChunkInfo->FormattedData == NULL)
|
||||
return 0;
|
||||
|
||||
RangeSet = ChunkInfo->FormattedData;
|
||||
RangeSet->Reserved = read_uint32(&b);
|
||||
RangeSet->Version = read_uint32(&b);
|
||||
memcpy(RangeSet->MagicNumber, b.Buffer, 4);
|
||||
skipbytes(&b, 4);
|
||||
RangeSet->RangeCount = read_uint32(&b);
|
||||
if(RangeSet->Reserved != 0 || RangeSet->Version > 2)
|
||||
return 0;
|
||||
if(RangeSet->RangeCount == 0)
|
||||
return 1;
|
||||
|
||||
RangeSet->Ranges = calloc(RangeSet->RangeCount, sizeof(IFFRangeEntry));
|
||||
if(RangeSet->Ranges == NULL)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<RangeSet->RangeCount; i++){
|
||||
unsigned s;
|
||||
IFFRangeEntry * Range = &RangeSet->Ranges[i];
|
||||
if(b.Size < 10)
|
||||
return 0;
|
||||
|
||||
Range->IsUsed = read_uint32(&b);
|
||||
Range->DefaultValue = read_uint32(&b);
|
||||
|
||||
for(s=0; s<2; s++){
|
||||
char ** string = (s==0) ? &Range->Name : &Range->Comment;
|
||||
if(b.Size == 0) return 0;
|
||||
|
||||
if(RangeSet->Version < 2){
|
||||
/* C string, possible padding */
|
||||
if(!read_c_string(&b, string))
|
||||
return 0;
|
||||
|
||||
/* Skip past the 0xA3 character;
|
||||
** see global.iff chunk 546 for why you can't do modulo-2 to detect this */
|
||||
if(b.Size && *b.Buffer == 0xA3)
|
||||
skipbytes(&b, 1);
|
||||
}else{
|
||||
/* Extended Pascal string, no padding */
|
||||
if(!read_pascal2_string(&b, string))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(RangeSet->Version != 0){
|
||||
if(b.Size < 5) return 0;
|
||||
Range->Enforced = read_uint8(&b);
|
||||
Range->RangeMin = read_uint16(&b);
|
||||
Range->RangeMax = read_uint16(&b);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iff_free_trcn(void * FormattedData){
|
||||
IFFRangeSet *RangeSet = FormattedData;
|
||||
if(RangeSet->Ranges){
|
||||
unsigned i;
|
||||
for(i=0; i<RangeSet->RangeCount; i++){
|
||||
IFFRangeEntry *Entry = &RangeSet->Ranges[i];
|
||||
free(Entry->Name);
|
||||
free(Entry->Comment);
|
||||
}
|
||||
}
|
||||
free(RangeSet->Ranges);
|
||||
}
|
0
library/formats/iff/ttab.c
Normal file
0
library/formats/iff/ttab.c
Normal file
Loading…
Add table
Add a link
Reference in a new issue