mirror of
https://github.com/simtactics/niotso.git
synced 2025-03-23 19:32:19 +00:00
Added support for SPR2, DGRP, and OBJf in the iff library and in iff2html.
This commit is contained in:
parent
bc978bfa0b
commit
e51ce26db9
11 changed files with 647 additions and 90 deletions
|
@ -5,11 +5,14 @@ set(IFF_SOURCES
|
||||||
cats.c
|
cats.c
|
||||||
iff.c
|
iff.c
|
||||||
bcon.c
|
bcon.c
|
||||||
|
dgrp.c
|
||||||
fcns.c
|
fcns.c
|
||||||
glob.c
|
glob.c
|
||||||
|
objf.c
|
||||||
palt.c
|
palt.c
|
||||||
rsmp.c
|
rsmp.c
|
||||||
spr.c
|
spr.c
|
||||||
|
spr2.c
|
||||||
str.c
|
str.c
|
||||||
string.c
|
string.c
|
||||||
tmpl.c
|
tmpl.c
|
||||||
|
|
108
Libraries/FileHandler/iff/dgrp.c
Normal file
108
Libraries/FileHandler/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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,13 +28,16 @@
|
||||||
void iff_free_##x(void *)
|
void iff_free_##x(void *)
|
||||||
|
|
||||||
iff_register(bcon);
|
iff_register(bcon);
|
||||||
|
iff_register(dgrp);
|
||||||
iff_register(str);
|
iff_register(str);
|
||||||
iff_register(cats);
|
iff_register(cats);
|
||||||
iff_register(c_string);
|
iff_register(c_string);
|
||||||
iff_register(glob);
|
iff_register(glob);
|
||||||
iff_register(fcns);
|
iff_register(fcns);
|
||||||
iff_register(palt);
|
iff_register(palt);
|
||||||
|
iff_register(objf);
|
||||||
iff_register(spr);
|
iff_register(spr);
|
||||||
|
iff_register(spr2);
|
||||||
iff_register(tmpl);
|
iff_register(tmpl);
|
||||||
iff_register(trcn);
|
iff_register(trcn);
|
||||||
iff_register(rsmp);
|
iff_register(rsmp);
|
||||||
|
@ -49,8 +52,11 @@ const char chunktypes[] =
|
||||||
"FCNS"
|
"FCNS"
|
||||||
"PALT"
|
"PALT"
|
||||||
"SPR#"
|
"SPR#"
|
||||||
|
"SPR2"
|
||||||
|
"DGRP"
|
||||||
"TMPL"
|
"TMPL"
|
||||||
"TRCN"
|
"TRCN"
|
||||||
|
"OBJf"
|
||||||
"rsmp"
|
"rsmp"
|
||||||
;
|
;
|
||||||
int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
|
int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
|
||||||
|
@ -62,8 +68,11 @@ int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
|
||||||
iff_parse_fcns,
|
iff_parse_fcns,
|
||||||
iff_parse_palt,
|
iff_parse_palt,
|
||||||
iff_parse_spr,
|
iff_parse_spr,
|
||||||
|
iff_parse_spr2,
|
||||||
|
iff_parse_dgrp,
|
||||||
iff_parse_tmpl,
|
iff_parse_tmpl,
|
||||||
iff_parse_trcn,
|
iff_parse_trcn,
|
||||||
|
iff_parse_objf,
|
||||||
iff_parse_rsmp
|
iff_parse_rsmp
|
||||||
};
|
};
|
||||||
void (* const iff_free_function[])(void*) = {
|
void (* const iff_free_function[])(void*) = {
|
||||||
|
@ -75,8 +84,11 @@ void (* const iff_free_function[])(void*) = {
|
||||||
iff_free_fcns,
|
iff_free_fcns,
|
||||||
NULL,
|
NULL,
|
||||||
iff_free_spr,
|
iff_free_spr,
|
||||||
|
iff_free_spr,
|
||||||
|
iff_free_dgrp,
|
||||||
iff_free_tmpl,
|
iff_free_tmpl,
|
||||||
iff_free_trcn,
|
iff_free_trcn,
|
||||||
|
iff_free_objf,
|
||||||
iff_free_rsmp
|
iff_free_rsmp
|
||||||
};
|
};
|
||||||
/* End */
|
/* End */
|
||||||
|
|
|
@ -83,6 +83,49 @@ typedef struct IFF_BCON_s
|
||||||
uint16_t * Constants;
|
uint16_t * Constants;
|
||||||
} IFF_BCON;
|
} IFF_BCON;
|
||||||
|
|
||||||
|
/* 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 */
|
/* FCNS chunk */
|
||||||
|
|
||||||
typedef struct IFFConstant_s
|
typedef struct IFFConstant_s
|
||||||
|
@ -101,6 +144,23 @@ typedef struct IFFConstantList_s
|
||||||
IFFConstant * Constants;
|
IFFConstant * Constants;
|
||||||
} IFFConstantList;
|
} 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 */
|
/* PALT chunk */
|
||||||
|
|
||||||
typedef struct IFFPalette_s
|
typedef struct IFFPalette_s
|
||||||
|
@ -112,15 +172,21 @@ typedef struct IFFPalette_s
|
||||||
uint8_t Data[256*3];
|
uint8_t Data[256*3];
|
||||||
} IFFPalette;
|
} IFFPalette;
|
||||||
|
|
||||||
/* SPR# chunk */
|
/* SPR#/SPR2 chunk */
|
||||||
|
|
||||||
typedef struct IFFSprite_s
|
typedef struct IFFSprite_s
|
||||||
{
|
{
|
||||||
uint32_t Reserved;
|
uint32_t Reserved;
|
||||||
uint16_t Height;
|
uint16_t Height;
|
||||||
uint16_t Width;
|
uint16_t Width;
|
||||||
|
uint32_t Flags;
|
||||||
|
uint16_t PaletteID;
|
||||||
|
uint16_t TransparentColor;
|
||||||
|
int16_t YLoc;
|
||||||
|
int16_t XLoc;
|
||||||
uint8_t * IndexData;
|
uint8_t * IndexData;
|
||||||
uint8_t * BGRA32Data;
|
uint8_t * BGRA32Data;
|
||||||
|
uint8_t * ZBuffer;
|
||||||
|
|
||||||
uint8_t InvalidDimensions;
|
uint8_t InvalidDimensions;
|
||||||
} IFFSprite;
|
} IFFSprite;
|
||||||
|
@ -133,6 +199,12 @@ typedef struct IFFSpriteList_s
|
||||||
IFFSprite * Sprites;
|
IFFSprite * Sprites;
|
||||||
} IFFSpriteList;
|
} IFFSpriteList;
|
||||||
|
|
||||||
|
enum IFFSpriteFlags {
|
||||||
|
IFFSPRITE_FLAG_COLOR = 1,
|
||||||
|
IFFSPRITE_FLAG_ZBUFFER = 2,
|
||||||
|
IFFSPRITE_FLAG_ALPHA = 4
|
||||||
|
};
|
||||||
|
|
||||||
int iff_depalette(IFFSprite * Sprite, const IFFPalette * Palette);
|
int iff_depalette(IFFSprite * Sprite, const IFFPalette * Palette);
|
||||||
|
|
||||||
/* STR# chunk */
|
/* STR# chunk */
|
||||||
|
|
60
Libraries/FileHandler/iff/objf.c
Normal file
60
Libraries/FileHandler/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);
|
||||||
|
}
|
|
@ -16,42 +16,41 @@
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "iffparser.h"
|
#include "iffparser.h"
|
||||||
|
|
||||||
int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||||
IFFSpriteList *SpriteList;
|
IFFSpriteList *SpriteList;
|
||||||
unsigned ChunkSize = ChunkInfo->Size;
|
|
||||||
bytestream b;
|
bytestream b;
|
||||||
|
unsigned NextSpriteOffset; /* Used for Version 1001 in place of the offset table */
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
if(ChunkSize < 12)
|
if(ChunkInfo->Size < 12)
|
||||||
return 0;
|
return 0;
|
||||||
set_bytestream(&b, Buffer, ChunkSize);
|
set_bytestream(&b, Buffer, ChunkInfo->Size);
|
||||||
|
if((Buffer[0]|Buffer[1]) == 0) b.Endian++; /* Big endian */
|
||||||
|
|
||||||
ChunkInfo->FormattedData = calloc(1, sizeof(IFFSpriteList));
|
ChunkInfo->FormattedData = calloc(1, sizeof(IFFSpriteList));
|
||||||
if(ChunkInfo->FormattedData == NULL)
|
if(ChunkInfo->FormattedData == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
SpriteList = ChunkInfo->FormattedData;
|
|
||||||
|
|
||||||
if((Buffer[0]|Buffer[1]) == 0) b.Endian++; /* Big endian */
|
SpriteList = ChunkInfo->FormattedData;
|
||||||
SpriteList->Version = read_uint32(&b);
|
SpriteList->Version = read_uint32(&b);
|
||||||
SpriteList->SpriteCount = read_uint32(&b);
|
SpriteList->SpriteCount = read_uint32(&b);
|
||||||
SpriteList->PaletteID = read_uint32(&b);
|
SpriteList->PaletteID = read_uint32(&b);
|
||||||
if(SpriteList->Version < 502 || (SpriteList->Version > 505 && SpriteList->Version != 1001))
|
if(SpriteList->Version < 502 || (SpriteList->Version > 505 && SpriteList->Version != 1001))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(SpriteList->Version == 1001){
|
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;
|
/* 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 */
|
** this is easy with the sprite size field */
|
||||||
|
for(SpriteList->SpriteCount = 0; b.Size >= 16; SpriteList->SpriteCount++){
|
||||||
/* At this point, we are looking at the first field of the first sprite */
|
|
||||||
|
|
||||||
for(SpriteList->SpriteCount = 0; b.Size >= 18; SpriteList->SpriteCount++){
|
|
||||||
if(read_uint32(&b) != 1001 || !skipbytes(&b, read_uint32(&b)))
|
if(read_uint32(&b) != 1001 || !skipbytes(&b, read_uint32(&b)))
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
seekto(&b, 12);
|
NextSpriteOffset = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SpriteList->SpriteCount == 0)
|
if(SpriteList->SpriteCount == 0)
|
||||||
|
@ -62,80 +61,89 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||||
|
|
||||||
for(i=0; i<SpriteList->SpriteCount; i++){
|
for(i=0; i<SpriteList->SpriteCount; i++){
|
||||||
IFFSprite * Sprite = &SpriteList->Sprites[i];
|
IFFSprite * Sprite = &SpriteList->Sprites[i];
|
||||||
unsigned SpriteSize = 0;
|
unsigned SpriteSize;
|
||||||
unsigned row = 0;
|
unsigned row = 0;
|
||||||
|
|
||||||
if(SpriteList->Version != 1001){
|
if(SpriteList->Version != 1001){
|
||||||
/* Jump to the next sprite using the offset table; this is mandatory */
|
/* Jump to the next sprite using the offset table; this is mandatory */
|
||||||
seekto(&b, 12 + 4*i);
|
seekto(&b, 12 + 4*i);
|
||||||
if(!seekto(&b, read_uint32(&b)))
|
if(!seekto(&b, read_uint32(&b)) || b.Size < 8)
|
||||||
return 0;
|
return 0;
|
||||||
if((SpriteSize = b.Size) < 10)
|
SpriteSize = b.Size;
|
||||||
return 0;
|
}else{
|
||||||
}
|
/* Jump to the next sprite using the sprite size field; this is mandatory */
|
||||||
|
seekto(&b, NextSpriteOffset);
|
||||||
if(SpriteList->Version == 1001){
|
|
||||||
seekto(&b, b.Buffer - b.StartPos); /* Resynchronize b.Size with b.Buffer */
|
|
||||||
if(b.Size < 18)
|
|
||||||
return 0;
|
|
||||||
read_uint32(&b); /* Sprite version; already checked to be equal to 1001 */
|
|
||||||
SpriteSize = read_uint32(&b);
|
SpriteSize = read_uint32(&b);
|
||||||
|
NextSpriteOffset += SpriteSize + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite->Reserved = read_uint32(&b);
|
Sprite->Reserved = read_uint32(&b);
|
||||||
Sprite->Height = read_uint16(&b);
|
Sprite->Height = read_uint16(&b);
|
||||||
Sprite->Width = read_uint16(&b);
|
Sprite->Width = read_uint16(&b);
|
||||||
if(Sprite->Reserved != 0 || Sprite->Height == 0 || Sprite->Width == 0 || Sprite->Height > UINT_MAX/Sprite->Width/2){
|
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 */
|
/* This happens in the third sprite of every SPR# chunk in sprites.iff */
|
||||||
Sprite->InvalidDimensions = 1;
|
Sprite->InvalidDimensions = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Sprite->IndexData = calloc(Sprite->Height*Sprite->Width, 2);
|
|
||||||
|
SpriteSize -= 8;
|
||||||
|
|
||||||
|
Sprite->IndexData = calloc(Sprite->Width*Sprite->Height, 2);
|
||||||
if(Sprite->IndexData == NULL)
|
if(Sprite->IndexData == NULL)
|
||||||
{printf("Error %u\n", 1);return 0;}
|
return 0;
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
/* Row command: valid commands are 0, 4, 5, and 9 */
|
/****
|
||||||
uint8_t Command, Count;
|
** Row command: valid commands are 0, 4, 5, 9, and 16
|
||||||
if(SpriteSize < 2)
|
*/
|
||||||
{printf("Error %u\n", 2);return 0;}
|
|
||||||
|
|
||||||
Command = *(b.Buffer++);
|
uint8_t RowCommand, RowCount;
|
||||||
Count = *(b.Buffer++);
|
|
||||||
|
if(SpriteSize < 2)
|
||||||
|
return 0;
|
||||||
|
RowCommand = *(b.Buffer++);
|
||||||
|
RowCount = *(b.Buffer++);
|
||||||
SpriteSize -= 2;
|
SpriteSize -= 2;
|
||||||
|
|
||||||
if(Command == 0 || Command == 16){
|
if(RowCommand == 0 || RowCommand == 16){
|
||||||
/* Start marker */
|
/* Start marker */
|
||||||
}else if(Command == 4){
|
}else if(RowCommand == 4){
|
||||||
/* Pixel command: valid commands are 1, 2, and 3 */
|
/****
|
||||||
|
** Pixel command: valid commands are 1, 2, and 3
|
||||||
|
*/
|
||||||
|
|
||||||
unsigned pixel = 0;
|
unsigned pixel = 0;
|
||||||
|
|
||||||
if(row == Sprite->Height || Count < 2 || (Count -= 2) > SpriteSize || Count%2 != 0)
|
if(row == Sprite->Height || RowCount < 2 || (RowCount -= 2) > SpriteSize || RowCount%2 != 0)
|
||||||
{printf("Error %u\n", 3);return 0;}
|
return 0;
|
||||||
SpriteSize -= Count;
|
SpriteSize -= RowCount;
|
||||||
while(Count){
|
|
||||||
|
while(RowCount){
|
||||||
uint8_t PixelCommand, PixelCount;
|
uint8_t PixelCommand, PixelCount;
|
||||||
if(Count < 2)
|
if(RowCount < 2)
|
||||||
{printf("Error %u\n", 4);return 0;}
|
return 0;
|
||||||
|
|
||||||
PixelCommand = *(b.Buffer++);
|
PixelCommand = *(b.Buffer++);
|
||||||
PixelCount = *(b.Buffer++);
|
PixelCount = *(b.Buffer++);
|
||||||
Count -= 2;
|
RowCount -= 2;
|
||||||
|
|
||||||
|
if(PixelCount > Sprite->Width - pixel)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if(PixelCommand == 1){
|
if(PixelCommand == 1){
|
||||||
/* Leave next n pixels as transparent */
|
/* Leave next n pixels as transparent */
|
||||||
if(PixelCount > Sprite->Width - pixel)
|
|
||||||
{printf("Error %u\n", 5);return 0;}
|
|
||||||
pixel += PixelCount;
|
pixel += PixelCount;
|
||||||
}else if(PixelCommand == 2){
|
}else if(PixelCommand == 2){
|
||||||
/* Set next n pixels to shared palette index */
|
/* Set next n pixels to shared palette index */
|
||||||
|
|
||||||
uint8_t PaletteIndex;
|
uint8_t PaletteIndex;
|
||||||
if(PixelCount > Sprite->Width - pixel || Count < 2)
|
if(RowCount < 2)
|
||||||
{printf("Error %u\n", 6);return 0;}
|
return 0;
|
||||||
|
|
||||||
PaletteIndex = *(b.Buffer++);
|
PaletteIndex = *(b.Buffer++);
|
||||||
b.Buffer++; /* Padding byte */
|
b.Buffer++; /* Padding byte */
|
||||||
Count -= 2;
|
RowCount -= 2;
|
||||||
|
|
||||||
while(PixelCount--){
|
while(PixelCount--){
|
||||||
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = PaletteIndex;
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = PaletteIndex;
|
||||||
|
@ -144,10 +152,11 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||||
}
|
}
|
||||||
}else if(PixelCommand == 3){
|
}else if(PixelCommand == 3){
|
||||||
/* Set next n pixels to n palette indices */
|
/* Set next n pixels to n palette indices */
|
||||||
|
|
||||||
int padding = PixelCount%2;
|
int padding = PixelCount%2;
|
||||||
if(PixelCount > Sprite->Width - pixel || PixelCount + padding > Count)
|
if(PixelCount + padding > RowCount)
|
||||||
{printf("Error %u\n", 7);return 0;}
|
return 0;
|
||||||
Count -= PixelCount + padding;
|
RowCount -= PixelCount + padding;
|
||||||
|
|
||||||
while(PixelCount--){
|
while(PixelCount--){
|
||||||
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = *(b.Buffer++);
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = *(b.Buffer++);
|
||||||
|
@ -155,18 +164,19 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
|
||||||
pixel++;
|
pixel++;
|
||||||
}
|
}
|
||||||
if(padding) b.Buffer++; /* Padding byte */
|
if(padding) b.Buffer++; /* Padding byte */
|
||||||
}else {printf("Error %u\n", 8);return 0;}
|
}else return 0;
|
||||||
}
|
}
|
||||||
row++;
|
row++;
|
||||||
}else if(Command == 5){
|
}else if(RowCommand == 5){
|
||||||
/* End marker */
|
/* End marker */
|
||||||
break;
|
break;
|
||||||
}else if(Command == 9){
|
}else if(RowCommand == 9){
|
||||||
/* Leave rows as transparent */
|
/* Leave rows as transparent */
|
||||||
if(Count > Sprite->Height - row)
|
|
||||||
{printf("Error %u\n", 9);return 0;}
|
if(RowCount > Sprite->Height - row)
|
||||||
row += Count;
|
return 0;
|
||||||
}else {printf("Error %u\n", 10);return 0;}
|
row += RowCount;
|
||||||
|
}else return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +191,7 @@ void iff_free_spr(void * FormattedData){
|
||||||
IFFSprite *Sprite = &SpriteList->Sprites[s];
|
IFFSprite *Sprite = &SpriteList->Sprites[s];
|
||||||
free(Sprite->IndexData);
|
free(Sprite->IndexData);
|
||||||
free(Sprite->BGRA32Data);
|
free(Sprite->BGRA32Data);
|
||||||
|
free(Sprite->ZBuffer);
|
||||||
}
|
}
|
||||||
free(SpriteList->Sprites);
|
free(SpriteList->Sprites);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,3 +15,210 @@
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
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 */
|
||||||
|
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;
|
||||||
|
|
||||||
|
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--){
|
||||||
|
Sprite->ZBuffer[Sprite->Width*row + pixel] = *(b.Buffer++);
|
||||||
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = *(b.Buffer++);
|
||||||
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 1] = 0xFF;
|
||||||
|
pixel++;
|
||||||
|
}
|
||||||
|
}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--){
|
||||||
|
Sprite->ZBuffer[Sprite->Width*row + pixel] = *(b.Buffer++);
|
||||||
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = *(b.Buffer++);
|
||||||
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 1] = *(b.Buffer++);
|
||||||
|
pixel++;
|
||||||
|
}
|
||||||
|
if(padding) b.Buffer++; /* Padding byte */
|
||||||
|
}else if(PixelCommand == 3){
|
||||||
|
/* Leave next n pixels as transparent */
|
||||||
|
|
||||||
|
pixel += PixelCount;
|
||||||
|
}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--){
|
||||||
|
Sprite->ZBuffer[Sprite->Width*row + pixel] = 0x00;
|
||||||
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = *(b.Buffer++);
|
||||||
|
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 1] = 0xFF;
|
||||||
|
pixel++;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
|
@ -302,26 +302,27 @@ int main(int argc, char *argv[]){
|
||||||
fprintf(hFile, "</div>\n");
|
fprintf(hFile, "</div>\n");
|
||||||
fprintf(hFile, "\n");
|
fprintf(hFile, "\n");
|
||||||
|
|
||||||
for(c=1, ChunkData = IFFFileInfo->Chunks; c <= IFFFileInfo->ChunkCount; c++, ChunkData++){
|
for(c=0, ChunkData = IFFFileInfo->Chunks; c < IFFFileInfo->ChunkCount; c++, ChunkData++){
|
||||||
fprintf(hFile, "<h2 id=\"chunk%u_%.4x\">%u [%s] (%.4X)%s%s <a href=\"#chunk%u_%.4x\">(Jump)</a></h2>\n",
|
fprintf(hFile, "<h2 id=\"chunk%u_%.4x\">%u [%s] (%.4X)%s%s <a href=\"#chunk%u_%.4x\">(Jump)</a></h2>\n",
|
||||||
c, ChunkData->ChunkID, c, ChunkData->Type, ChunkData->ChunkID,
|
c+1, ChunkData->ChunkID, c+1, ChunkData->Type, ChunkData->ChunkID,
|
||||||
(ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label,
|
(ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label,
|
||||||
c, ChunkData->ChunkID);
|
c+1, ChunkData->ChunkID);
|
||||||
fprintf(hFile, "<div>\n");
|
fprintf(hFile, "<div>\n");
|
||||||
|
|
||||||
if(ChunkData->FormattedData == NULL){
|
if(ChunkData->FormattedData == NULL){
|
||||||
int success = 0;
|
int success = 0;
|
||||||
/* The iff library does not parse BMP_ or FBMP chunks */
|
/* The iff library does not parse BMP_ or FBMP chunks */
|
||||||
if(!strcmp(ChunkData->Type, "BMP_") || !strcmp(ChunkData->Type, "FBMP")){
|
if(!strcmp(ChunkData->Type, "BMP_") || !strcmp(ChunkData->Type, "FBMP")){
|
||||||
|
int bmp = !strcmp(ChunkData->Type, "BMP_");
|
||||||
size_t Width, Height;
|
size_t Width, Height;
|
||||||
char filename[32];
|
char filename[32];
|
||||||
sprintf(filename, "%sbmp_%u_%.4x.png", OutDir, c+1, ChunkData->ChunkID);
|
sprintf(filename, "%s%s_%u_%.4x.png", OutDir, bmp ? "bmp" : "fbmp", c+1, ChunkData->ChunkID);
|
||||||
|
|
||||||
if(WritePNG(filename, ChunkData, NULL, &Width, &Height)){
|
if(WritePNG(filename, ChunkData, 0, NULL, &Width, &Height)){
|
||||||
fprintf(hFile, "<table class=\"center centerall\">\n");
|
fprintf(hFile, "<table class=\"center centerall\">\n");
|
||||||
fprintf(hFile, "<tr><th>Image</th></tr>\n");
|
fprintf(hFile, "<tr><th>Image</th></tr>\n");
|
||||||
fprintf(hFile, "<tr><td><img src=\"bmp_%u_%.4x.png\" width=\"%u\" height=\"%u\" alt=\"\" /></td></tr>\n",
|
fprintf(hFile, "<tr><td><img src=\"%s_%u_%.4x.png\" width=\"%u\" height=\"%u\" alt=\"\" /></td></tr>\n",
|
||||||
c+1, ChunkData->ChunkID, Width, Height);
|
bmp ? "bmp" : "fbmp", c+1, ChunkData->ChunkID, Width, Height);
|
||||||
fprintf(hFile, "</table>\n");
|
fprintf(hFile, "</table>\n");
|
||||||
success++;
|
success++;
|
||||||
}
|
}
|
||||||
|
@ -536,11 +537,12 @@ int main(int argc, char *argv[]){
|
||||||
fprintf(hFile, "</tr>\n");
|
fprintf(hFile, "</tr>\n");
|
||||||
}
|
}
|
||||||
fprintf(hFile, "</table>\n");
|
fprintf(hFile, "</table>\n");
|
||||||
}else if(!strcmp(ChunkData->Type, "SPR#")){
|
}else if(!strcmp(ChunkData->Type, "SPR#") || !strcmp(ChunkData->Type, "SPR2")){
|
||||||
/****
|
/****
|
||||||
** SPR# parsing
|
** SPR# and SPR2 parsing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int spr1 = !strcmp(ChunkData->Type, "SPR#");
|
||||||
IFFSpriteList * SpriteList = ChunkData->FormattedData;
|
IFFSpriteList * SpriteList = ChunkData->FormattedData;
|
||||||
IFFChunk * Palette = NULL;
|
IFFChunk * Palette = NULL;
|
||||||
IFFPalette BlankPalette;
|
IFFPalette BlankPalette;
|
||||||
|
@ -565,21 +567,98 @@ int main(int argc, char *argv[]){
|
||||||
}else PaletteData = Palette->FormattedData;
|
}else PaletteData = Palette->FormattedData;
|
||||||
|
|
||||||
fprintf(hFile, "<table class=\"center centerall\">\n");
|
fprintf(hFile, "<table class=\"center centerall\">\n");
|
||||||
fprintf(hFile, "<tr><th colspan=\"2\">Sprite</th></tr>\n");
|
fprintf(hFile, "<tr><th colspan=\"2\">Sprite</th>");
|
||||||
|
if(!spr1) fprintf(hFile, "<th>Z-Buffer</th>");
|
||||||
|
fprintf(hFile, "</tr>\n");
|
||||||
for(i=0; i<SpriteList->SpriteCount; i++){
|
for(i=0; i<SpriteList->SpriteCount; i++){
|
||||||
IFFSprite * Sprite = &SpriteList->Sprites[i];
|
IFFSprite * Sprite = &SpriteList->Sprites[i];
|
||||||
char filename[32];
|
char filename[32];
|
||||||
sprintf(filename, "%sspr1_%u_%.4x_%u.png", OutDir, c+1, ChunkData->ChunkID, i+1);
|
sprintf(filename, "%s%s_%u_%.4x_%u.png", OutDir, spr1 ? "spr1" : "spr2", c+1, ChunkData->ChunkID, i+1);
|
||||||
|
|
||||||
fprintf(hFile, "<tr><td>%u</td><td>", i+1);
|
fprintf(hFile, "<tr><td>%u</td><td", i+1);
|
||||||
if(Sprite->IndexData && iff_depalette(Sprite, PaletteData) && WritePNG(filename, NULL, Sprite, NULL, NULL))
|
if(Sprite->IndexData && iff_depalette(Sprite, PaletteData)){
|
||||||
fprintf(hFile, "<img src=\"spr1_%u_%.4x_%u.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
|
WritePNG(filename, NULL, 0, Sprite, NULL, NULL);
|
||||||
|
fprintf(hFile, "><img src=\"%s_%u_%.4x_%u.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
|
||||||
|
spr1 ? "spr1" : "spr2", c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height);
|
||||||
|
if(!spr1){
|
||||||
|
sprintf(filename, "%sspr2_%u_%.4x_%u_z.png", OutDir, c+1, ChunkData->ChunkID, i+1);
|
||||||
|
if(Sprite->ZBuffer){
|
||||||
|
WritePNG(filename, NULL, 1, Sprite, NULL, NULL);
|
||||||
|
fprintf(hFile, "</td><td><img src=\"spr2_%u_%.4x_%u_z.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
|
||||||
c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height);
|
c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height);
|
||||||
else
|
}else
|
||||||
fprintf(hFile, Sprite->InvalidDimensions ? "Blank sprite" : "This sprite cannot be displayed.");
|
fprintf(hFile, "None provided");
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
fprintf(hFile, Sprite->InvalidDimensions ? "%sBlank sprite" : "%sThis sprite cannot be displayed.",
|
||||||
|
!spr1 ? " colspan=\"2\">" : "");
|
||||||
fprintf(hFile, "</td></tr>\n");
|
fprintf(hFile, "</td></tr>\n");
|
||||||
}
|
}
|
||||||
fprintf(hFile, "</table>\n");
|
fprintf(hFile, "</table>\n");
|
||||||
|
}else if(!strcmp(ChunkData->Type, "DGRP")){
|
||||||
|
/****
|
||||||
|
** DGRP parsing
|
||||||
|
*/
|
||||||
|
|
||||||
|
IFFDrawGroup * Group = ChunkData->FormattedData;
|
||||||
|
IFFDrawAngle * Angle;
|
||||||
|
IFFSpriteInfo * Sprite;
|
||||||
|
unsigned i,j;
|
||||||
|
const char * Zooms[] = {"Far", "Middle", "Close"};
|
||||||
|
|
||||||
|
fprintf(hFile, "<table>\n");
|
||||||
|
fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Group->Version);
|
||||||
|
fprintf(hFile, "</table>\n");
|
||||||
|
fprintf(hFile, "<br />\n");
|
||||||
|
|
||||||
|
fprintf(hFile, "<table class=\"center\">\n");
|
||||||
|
fprintf(hFile, "<tr><th>Direction</th><th>Zoom</th><th colspan=\"6\">Sprite</th></tr>\n");
|
||||||
|
for(i=0, Angle=Group->DrawAngles; i<12; i++, Angle++){
|
||||||
|
const char * Direction =
|
||||||
|
(Angle->Direction == IFFDIRECTION_NORTHEAST) ? "North east" :
|
||||||
|
(Angle->Direction == IFFDIRECTION_SOUTHEAST) ? "South east" :
|
||||||
|
(Angle->Direction == IFFDIRECTION_NORTHWEST) ? "North west" :
|
||||||
|
"South west";
|
||||||
|
|
||||||
|
if(Angle->SpriteCount){
|
||||||
|
fprintf(hFile,
|
||||||
|
"<tr><td rowspan=\"%u\">%s</td><td rowspan=\"%u\">%s</td>"
|
||||||
|
"<th>#</th><th>Type</th><th>Chunk ID</th><th>Sprite index</th>"
|
||||||
|
"<th>Flags</th><th>Sprite offset</th><th>Object offset</th></tr>\n",
|
||||||
|
1+Angle->SpriteCount, Direction, 1+Angle->SpriteCount, Zooms[Angle->Zoom-1]);
|
||||||
|
for(j=0, Sprite = Angle->SpriteInfo; j<Angle->SpriteCount; j++, Sprite++)
|
||||||
|
fprintf(hFile, "<tr><td>%u</td><td>%u</td><td>%.4X</td><td>%u</td><td>%u</td>"
|
||||||
|
"<td>(%+d,%+d)</td><td>(%+g,%+g,%+g)</td></tr>",
|
||||||
|
j+1, Sprite->Type, Sprite->ChunkID, Sprite->SpriteIndex, Sprite->Flags,
|
||||||
|
Sprite->SpriteX, Sprite->SpriteY, Sprite->ObjectX, Sprite->ObjectY, Sprite->ObjectZ);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
fprintf(hFile, "<tr><td>%s</td><td>%s</td><td>None specified</td></tr>", Direction, Zooms[Angle->Zoom-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(hFile, "</table>\n");
|
||||||
|
}else if(!strcmp(ChunkData->Type, "OBJf")){
|
||||||
|
/****
|
||||||
|
** OBJf parsing
|
||||||
|
*/
|
||||||
|
|
||||||
|
IFFFunctionTable * Table = ChunkData->FormattedData;
|
||||||
|
fprintf(hFile, "<table>\n");
|
||||||
|
fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Table->Version);
|
||||||
|
fprintf(hFile, "</table>\n");
|
||||||
|
|
||||||
|
if(Table->FunctionCount > 0){
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
fprintf(hFile, "<br />\n");
|
||||||
|
fprintf(hFile, "<table class=\"center\">\n");
|
||||||
|
fprintf(hFile, "<tr><th colspan=\"2\">Condition function</th><th>Action function</th></tr>\n");
|
||||||
|
for(i=0; i<Table->FunctionCount; i++)
|
||||||
|
fprintf(hFile,
|
||||||
|
"<tr><td>%u</td><td>%.4X</td><td>%.4X</td></tr>\n",
|
||||||
|
i+1, Table->Functions[i].ConditionID, Table->Functions[i].ActionID);
|
||||||
|
fprintf(hFile, "</table>\n");
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
fprintf(hFile, "The contents of this chunk cannot be shown on this page.\n");
|
fprintf(hFile, "The contents of this chunk cannot be shown on this page.\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
#include <libpng/png.h>
|
#include <libpng/png.h>
|
||||||
#include "opngreduc.h"
|
#include "opngreduc.h"
|
||||||
|
|
||||||
int WritePNG(const char * OutName, const IFFChunk * ChunkData, const IFFSprite * Sprite, size_t * Width, size_t * Height){
|
int WritePNG(const char * OutName, const IFFChunk * ChunkData, int ZBuffer,
|
||||||
|
const IFFSprite * Sprite, size_t * Width, size_t * Height){
|
||||||
FILE * hFile;
|
FILE * hFile;
|
||||||
png_structp png_ptr;
|
png_structp png_ptr;
|
||||||
png_infop info_ptr;
|
png_infop info_ptr;
|
||||||
|
@ -40,7 +41,7 @@ int WritePNG(const char * OutName, const IFFChunk * ChunkData, const IFFSprite *
|
||||||
/* BMP_ or FBMP chunk */
|
/* BMP_ or FBMP chunk */
|
||||||
bmpheader_t BMPHeader;
|
bmpheader_t BMPHeader;
|
||||||
|
|
||||||
if(!bmp_read_header(&BMPHeader, ChunkData->Data, ChunkData->Size - 76))
|
if(!bmp_read_header(&BMPHeader, ChunkData->Data, ChunkData->Size))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Image.Data = malloc(BMPHeader.DecompressedSize);
|
Image.Data = malloc(BMPHeader.DecompressedSize);
|
||||||
|
@ -57,8 +58,9 @@ int WritePNG(const char * OutName, const IFFChunk * ChunkData, const IFFSprite *
|
||||||
/* SPR# or SPR2 sprite */
|
/* SPR# or SPR2 sprite */
|
||||||
Image.Width = Sprite->Width;
|
Image.Width = Sprite->Width;
|
||||||
Image.Height = Sprite->Height;
|
Image.Height = Sprite->Height;
|
||||||
Image.Data = Sprite->BGRA32Data;
|
Image.Data = (!ZBuffer) ? Sprite->BGRA32Data : Sprite->ZBuffer;
|
||||||
|
|
||||||
|
if(!ZBuffer){
|
||||||
/* Swap from BGR to RGB; this cannot be done with libpng when you use opng_reduce_image
|
/* Swap from BGR to RGB; this cannot be done with libpng when you use opng_reduce_image
|
||||||
** due to the state that it leaves png_ptr in */
|
** due to the state that it leaves png_ptr in */
|
||||||
for(i=0; i<Image.Width*Image.Height; i++){
|
for(i=0; i<Image.Width*Image.Height; i++){
|
||||||
|
@ -67,6 +69,7 @@ int WritePNG(const char * OutName, const IFFChunk * ChunkData, const IFFSprite *
|
||||||
Image.Data[i*4 + 2] = temp;
|
Image.Data[i*4 + 2] = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
row_pointers = malloc(Image.Height * sizeof(png_bytep));
|
row_pointers = malloc(Image.Height * sizeof(png_bytep));
|
||||||
if(row_pointers == NULL){
|
if(row_pointers == NULL){
|
||||||
|
@ -74,7 +77,7 @@ int WritePNG(const char * OutName, const IFFChunk * ChunkData, const IFFSprite *
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(i=0; i<Image.Height; i++)
|
for(i=0; i<Image.Height; i++)
|
||||||
row_pointers[i] = Image.Data + Image.Width*((ChunkData) ? 3*(Image.Height-i-1) : 4*i);
|
row_pointers[i] = Image.Data + Image.Width*((ChunkData) ? 3*(Image.Height-i-1) : ((!ZBuffer)?4:1)*i);
|
||||||
|
|
||||||
/****
|
/****
|
||||||
** PNG handling
|
** PNG handling
|
||||||
|
@ -118,7 +121,8 @@ int WritePNG(const char * OutName, const IFFChunk * ChunkData, const IFFSprite *
|
||||||
png_set_compression_window_bits(png_ptr, 15);
|
png_set_compression_window_bits(png_ptr, 15);
|
||||||
png_set_compression_buffer_size(png_ptr, 32768);
|
png_set_compression_buffer_size(png_ptr, 32768);
|
||||||
|
|
||||||
png_set_IHDR(png_ptr, info_ptr, Image.Width, Image.Height, 8, ChunkData ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA,
|
png_set_IHDR(png_ptr, info_ptr, Image.Width, Image.Height, 8,
|
||||||
|
ChunkData ? PNG_COLOR_TYPE_RGB : (!ZBuffer) ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_GRAY,
|
||||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
png_set_rows(png_ptr, info_ptr, row_pointers);
|
png_set_rows(png_ptr, info_ptr, row_pointers);
|
||||||
|
|
|
@ -16,4 +16,5 @@
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int WritePNG(const char * OutName, const IFFChunk * ChunkData, const IFFSprite * Sprite, size_t * Width, size_t * Height);
|
int WritePNG(const char * OutName, const IFFChunk * ChunkData, int ZBuffer,
|
||||||
|
const IFFSprite * Sprite, size_t * Width, size_t * Height);
|
Loading…
Add table
Reference in a new issue