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

@ -16,3 +16,76 @@
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