Added BHAV parsing and displaying, and started using the transparent color field in SPR2 chunks to remove the magenta background in some sprites.

This commit is contained in:
Fatbag 2012-06-15 20:45:11 -05:00
parent e51ce26db9
commit dd15e0d42a
7 changed files with 160 additions and 26 deletions

View file

@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.6)
project(iff)
set(IFF_SOURCES
bhav.c
cats.c
iff.c
bcon.c

View file

@ -15,4 +15,77 @@
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);
}

View file

@ -35,6 +35,7 @@ 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);
@ -56,6 +57,7 @@ const char chunktypes[] =
"DGRP"
"TMPL"
"TRCN"
"BHAV"
"OBJf"
"rsmp"
;
@ -72,6 +74,7 @@ int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
iff_parse_dgrp,
iff_parse_tmpl,
iff_parse_trcn,
iff_parse_bhav,
iff_parse_objf,
iff_parse_rsmp
};
@ -88,6 +91,7 @@ void (* const iff_free_function[])(void*) = {
iff_free_dgrp,
iff_free_tmpl,
iff_free_trcn,
iff_free_bhav,
iff_free_objf,
iff_free_rsmp
};

View file

@ -83,6 +83,27 @@ typedef struct IFF_BCON_s
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

View file

@ -120,6 +120,7 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
while(RowCount){
uint8_t PixelCommand, PixelCount;
uint8_t * IndexData;
if(RowCount < 2)
return 0;
@ -130,10 +131,11 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
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 */
pixel += PixelCount;
}else if(PixelCommand == 2){
/* Set next n pixels to shared palette index */
@ -146,9 +148,8 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
RowCount -= 2;
while(PixelCount--){
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = PaletteIndex;
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 1] = 0xFF;
pixel++;
*IndexData++ = PaletteIndex;
*IndexData++ = 0xFF;
}
}else if(PixelCommand == 3){
/* Set next n pixels to n palette indices */
@ -159,9 +160,8 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
RowCount -= PixelCount + padding;
while(PixelCount--){
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 0] = *(b.Buffer++);
Sprite->IndexData[(Sprite->Width*row + pixel)*2 + 1] = 0xFF;
pixel++;
*IndexData++ = *(b.Buffer++);
*IndexData++ = 0xFF;
}
if(padding) b.Buffer++; /* Padding byte */
}else return 0;

View file

@ -144,6 +144,7 @@ int iff_parse_spr2(IFFChunk * ChunkInfo, const uint8_t * Buffer){
while(RowCount){
uint8_t PixelCommand; /* 3 bits */
uint16_t PixelCount; /* 13 bits */
uint8_t * IndexData, * ZBuffer;
if(RowCount < 2)
return 0;
@ -157,6 +158,10 @@ int iff_parse_spr2(IFFChunk * ChunkInfo, const uint8_t * Buffer){
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 */
@ -165,10 +170,10 @@ int iff_parse_spr2(IFFChunk * ChunkInfo, const uint8_t * Buffer){
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++;
*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 */
@ -179,16 +184,13 @@ int iff_parse_spr2(IFFChunk * ChunkInfo, const uint8_t * Buffer){
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++;
*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 */
pixel += PixelCount;
}else if(PixelCommand == 6){
/* color: Set next n pixels to n palette indices */
@ -198,10 +200,11 @@ int iff_parse_spr2(IFFChunk * ChunkInfo, const uint8_t * Buffer){
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++;
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;

View file

@ -578,20 +578,20 @@ int main(int argc, char *argv[]){
fprintf(hFile, "<tr><td>%u</td><td", i+1);
if(Sprite->IndexData && iff_depalette(Sprite, PaletteData)){
WritePNG(filename, NULL, 0, Sprite, NULL, NULL);
fprintf(hFile, "><img src=\"%s_%u_%.4x_%u.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
fprintf(hFile, "><img src=\"%s_%u_%.4x_%u.png\" width=\"%u\" height=\"%u\" alt=\"\" /></td><td>",
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=\"\" />",
fprintf(hFile, "<img src=\"spr2_%u_%.4x_%u_z.png\" width=\"%u\" height=\"%u\" alt=\"\" />",
c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height);
}else
fprintf(hFile, "None provided");
}
}else
fprintf(hFile, Sprite->InvalidDimensions ? "%sBlank sprite" : "%sThis sprite cannot be displayed.",
!spr1 ? " colspan=\"2\">" : "");
!spr1 ? " colspan=\"2\">" : ">");
fprintf(hFile, "</td></tr>\n");
}
fprintf(hFile, "</table>\n");
@ -637,6 +637,38 @@ int main(int argc, char *argv[]){
}
}
fprintf(hFile, "</table>\n");
}else if(!strcmp(ChunkData->Type, "BHAV")){
/****
** BHAV parsing
*/
IFFBehavior * Behavior = ChunkData->FormattedData;
IFFInstruction * Instruction;
fprintf(hFile, "<table>\n");
fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Behavior->Version);
fprintf(hFile, "<tr><td>Type:</td><td>%u</td></tr>\n", Behavior->Type);
fprintf(hFile, "<tr><td>Arguments:</td><td>%u</td></tr>\n", Behavior->ArgumentCount);
fprintf(hFile, "<tr><td>Locals:</td><td>%u</td></tr>\n", Behavior->LocalCount);
fprintf(hFile, "<tr><td>Flags:</td><td>%.4X</td></tr>\n", Behavior->Flags);
fprintf(hFile, "</table>\n");
if(Behavior->InstructionCount > 0){
unsigned i;
fprintf(hFile, "<br />\n");
fprintf(hFile, "<table class=\"center\">\n");
fprintf(hFile, "<tr><th colspan=\"2\">Opcode</th><th>T-Dest</th><th>F-Dest</th><th>Operand data</th></tr>\n");
for(i=0, Instruction = Behavior->Instructions; i<Behavior->InstructionCount; i++, Instruction++)
fprintf(hFile, "<tr><td>%u</td><td><tt>%.4X</tt></td><td>%u</td><td>%u</td>"
"<td><tt>%.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X</tt></td></tr>\n",
i, Instruction->Opcode, Instruction->TDest, Instruction->FDest,
Instruction->Operands[0], Instruction->Operands[1],
Instruction->Operands[2], Instruction->Operands[3],
Instruction->Operands[4], Instruction->Operands[5],
Instruction->Operands[6], Instruction->Operands[7]);
fprintf(hFile, "</table>\n");
}
}else if(!strcmp(ChunkData->Type, "OBJf")){
/****
** OBJf parsing