mirror of
https://github.com/simtactics/niotso.git
synced 2025-03-15 08:11:22 +00:00
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:
parent
e51ce26db9
commit
dd15e0d42a
7 changed files with 160 additions and 26 deletions
|
@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.6)
|
|||
project(iff)
|
||||
|
||||
set(IFF_SOURCES
|
||||
bhav.c
|
||||
cats.c
|
||||
iff.c
|
||||
bcon.c
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue