diff --git a/Libraries/FileHandler/iff/CMakeLists.txt b/Libraries/FileHandler/iff/CMakeLists.txt index ebd6d42..b7e0197 100644 --- a/Libraries/FileHandler/iff/CMakeLists.txt +++ b/Libraries/FileHandler/iff/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.6) project(iff) set(IFF_SOURCES + bhav.c cats.c iff.c bcon.c diff --git a/Libraries/FileHandler/iff/bhav.c b/Libraries/FileHandler/iff/bhav.c index b3a8988..41f57d3 100644 --- a/Libraries/FileHandler/iff/bhav.c +++ b/Libraries/FileHandler/iff/bhav.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. -*/ \ No newline at end of file +*/ + +#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; iInstructionCount; 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); +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iff.c b/Libraries/FileHandler/iff/iff.c index 94c9f5c..04e53c3 100644 --- a/Libraries/FileHandler/iff/iff.c +++ b/Libraries/FileHandler/iff/iff.c @@ -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 }; diff --git a/Libraries/FileHandler/iff/iff.h b/Libraries/FileHandler/iff/iff.h index 1199c28..61218db 100644 --- a/Libraries/FileHandler/iff/iff.h +++ b/Libraries/FileHandler/iff/iff.h @@ -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 diff --git a/Libraries/FileHandler/iff/spr.c b/Libraries/FileHandler/iff/spr.c index 04c32cb..c3db0dd 100644 --- a/Libraries/FileHandler/iff/spr.c +++ b/Libraries/FileHandler/iff/spr.c @@ -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; diff --git a/Libraries/FileHandler/iff/spr2.c b/Libraries/FileHandler/iff/spr2.c index 436ab62..e37df23 100644 --- a/Libraries/FileHandler/iff/spr2.c +++ b/Libraries/FileHandler/iff/spr2.c @@ -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; diff --git a/Tools/iff2html/iff2html.c b/Tools/iff2html/iff2html.c index 9debdbd..a631e3c 100644 --- a/Tools/iff2html/iff2html.c +++ b/Tools/iff2html/iff2html.c @@ -578,20 +578,20 @@ int main(int argc, char *argv[]){ fprintf(hFile, "%uIndexData && iff_depalette(Sprite, PaletteData)){ WritePNG(filename, NULL, 0, Sprite, NULL, NULL); - fprintf(hFile, ">\"\"", + fprintf(hFile, ">\"\"", 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, "\"\"", + fprintf(hFile, "\"\"", 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, "\n"); } fprintf(hFile, "\n"); @@ -637,6 +637,38 @@ int main(int argc, char *argv[]){ } } fprintf(hFile, "\n"); + }else if(!strcmp(ChunkData->Type, "BHAV")){ + /**** + ** BHAV parsing + */ + + IFFBehavior * Behavior = ChunkData->FormattedData; + IFFInstruction * Instruction; + + fprintf(hFile, "\n"); + fprintf(hFile, "\n", Behavior->Version); + fprintf(hFile, "\n", Behavior->Type); + fprintf(hFile, "\n", Behavior->ArgumentCount); + fprintf(hFile, "\n", Behavior->LocalCount); + fprintf(hFile, "\n", Behavior->Flags); + fprintf(hFile, "
Version:%u
Type:%u
Arguments:%u
Locals:%u
Flags:%.4X
\n"); + + if(Behavior->InstructionCount > 0){ + unsigned i; + + fprintf(hFile, "
\n"); + fprintf(hFile, "\n"); + fprintf(hFile, "\n"); + for(i=0, Instruction = Behavior->Instructions; iInstructionCount; i++, Instruction++) + fprintf(hFile, "" + "\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, "
OpcodeT-DestF-DestOperand data
%u%.4X%u%u%.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X
\n"); + } }else if(!strcmp(ChunkData->Type, "OBJf")){ /**** ** OBJf parsing