From 2186d5f3f95cd74a070a490d899291648d58667a Mon Sep 17 00:00:00 2001 From: Steven Fuller Date: Sun, 1 Jul 2001 00:55:22 +0000 Subject: Initial revision --- src/win95/chunkpal.cpp | 1007 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1007 insertions(+) create mode 100644 src/win95/chunkpal.cpp (limited to 'src/win95/chunkpal.cpp') diff --git a/src/win95/chunkpal.cpp b/src/win95/chunkpal.cpp new file mode 100644 index 0000000..0cf1185 --- /dev/null +++ b/src/win95/chunkpal.cpp @@ -0,0 +1,1007 @@ +#include "chunkpal.hpp" +#include "mishchnk.hpp" + +#if engine + +#ifndef UseLocalAssert +#define UseLocalAssert 1 +#endif +#include "ourasert.h" +#define assert(x) GLOBALASSERT(x) + +#else + +#if cencon +#include "ccassert.h" +#else +#include +#endif + +#endif +//macro for helping to force inclusion of chunks when using libraries +FORCE_CHUNK_INCLUDE_IMPLEMENT(chunkpal) + +/////////////////////////////////////// + +// Class Environment_Palette_Chunk functions + + +void Palette_Outdated(Chunk_With_Children * parent) +{ + if (parent) + { + List plist; + parent->lookup_child("ENVPALET",plist); + for (LIF plit(&plist); !plit.done(); plit.next()) + { + ((Environment_Palette_Chunk *)plit())->flags &= ~EnvPalFlag_UpToDate; + } + } +} + +void FixedPalette_Outdated(Chunk_With_Children * parent) +{ + if (parent) + { + List plist; + parent->lookup_child("PRSETPAL",plist); + for (LIF plit(&plist); !plit.done(); plit.next()) + { + for (LIF findconst(&((Preset_Palette_Chunk *)plit())->pplist); !findconst.done(); findconst.next()) + { + Preset_Palette temp = findconst(); + if (temp.flags & PrePalFlag_Reserved) + { + temp.flags &= ~PrePalFlag_UpToDate; + findconst.change_current(temp); + } + } + } + } +} + +BOOL IsFixedPalette(Chunk_With_Children * parent) +{ + if (parent) + { + List plist; + parent->lookup_child("PRSETPAL",plist); + for (LIF plit(&plist); !plit.done(); plit.next()) + { + for (LIF findconst(&((Preset_Palette_Chunk *)plit())->pplist); !findconst.done(); findconst.next()) + { + if (findconst().flags & PrePalFlag_Reserved) + { + return TRUE; + } + } + } + parent->lookup_child("SETPALST",plist); + for (plit = LIF (&plist); !plit.done(); plit.next()) + { + for (LIF findconst(&((Preset_Palette_Store_Chunk *)plit())->pplist); !findconst.done(); findconst.next()) + { + if (findconst().flags & PrePalFlag_Reserved) + { + return TRUE; + } + } + } + } + return FALSE; +} + +RIF_IMPLEMENT_DYNCREATE("ENVPALET",Environment_Palette_Chunk) + +Environment_Palette_Chunk::~Environment_Palette_Chunk () +{ + if (pixel_data) + { + unsigned char * temp_pd = (unsigned char *)pixel_data; + delete [] temp_pd; + } +} + +size_t Environment_Palette_Chunk::size_chunk() +{ + chunk_size = 12 + 8 + (width * height * 3 + 3 & ~3); + return chunk_size; +} + +void Environment_Palette_Chunk::fill_data_block (char * data_start) +{ + strncpy (data_start, identifier, 8); + + data_start += 8; + + *((int *) data_start) = chunk_size; + + data_start += 4; + + *((int*)data_start) = width * height; + *((int*)(data_start+4)) = flags; + + data_start += 8; + + for (int i=0; i<(width*height*3); i++) + { + data_start[i] = pixel_data[i]; + } + +} + + +/////////////////////////////////////// + +// Class Preset_Palette_Chunk functions + + +Preset_Palette::~Preset_Palette () +{ + if (pixel_data) + { + unsigned char * temp_pd = (unsigned char *)pixel_data; + delete [] temp_pd; + } + if (name) delete[] name; +} + +Preset_Palette::Preset_Palette (Preset_Palette const & c) +: size(c.size) +, flags(c.flags) +, reserved1(c.reserved1) +, reserved2(c.reserved2) +, startpos(c.startpos) +, pixel_data(grab_pixel_data(c.size, c.pixel_data)) +, name(0) +{ + if (c.name) + { + name = new char[strlen(c.name)+1]; + strcpy(name,c.name); + } +} + +Preset_Palette & Preset_Palette::operator = (Preset_Palette const & c) +{ + if (pixel_data) + { + unsigned char * temp_pd = (unsigned char *)pixel_data; + delete [] temp_pd; + } + if (name) + { + delete[] name; + name = 0; + } + if (c.name) + { + name = new char[strlen(c.name)+1]; + strcpy(name,c.name); + } + + *(int *)&size = c.size; + *(int *)&flags = c.flags; + *(int *)&reserved1 = c.reserved1; + *(int *)&reserved2 = c.reserved2; + *(int *)&startpos = c.startpos; + + *(const unsigned char * *)&pixel_data = grab_pixel_data(c.size,c.pixel_data); + + return *this; +} + + + +size_t Preset_Palette::size_chunk() const +{ + return 20 + (size * 3 + (name ? strlen(name)+1 : 8) +3 &~3); +} + +void Preset_Palette::fill_data_block (char * data_start) +{ + *(int*)data_start = size; + *(int*)(data_start+4) = flags; + *(int*)(data_start+8) = reserved1; + *(int*)(data_start+12) = reserved2; + *(int*)(data_start+16) = startpos; + + data_start += 20; + + unsigned char const * sptr = pixel_data; + + for (int i=size*3; i; --i, ++sptr, ++data_start) + { + *data_start = *sptr; + } + strcpy(data_start,name ? name : "unnamed"); +} + +RIF_IMPLEMENT_DYNCREATE("PRSETPAL",Preset_Palette_Chunk) + +Preset_Palette_Chunk::Preset_Palette_Chunk(Chunk_With_Children * const parent, char const * sdata, size_t const /*ssize*/) +: Chunk(parent,"PRSETPAL") +, version_num(*(int *)sdata) +, flags(*(int *)(sdata+4)) +, reserved1(*(int *)(sdata+8)) +, reserved2(*(int *)(sdata+12)) +, reserved3(*(int *)(sdata+16)) +{ + int const pplistsize = *(int *)(sdata+20); + sdata += 24; + + for (int i = pplistsize; i; --i) + { + Preset_Palette current(sdata); + sdata += current.size_chunk(); + pplist.add_entry(current); + } +} + + +size_t Preset_Palette_Chunk::size_chunk () +{ + chunk_size = 12 + 24; + + for (LIF li(&pplist); !li.done(); li.next()) + { + chunk_size += li().size_chunk(); + } + + return chunk_size; +} + +void Preset_Palette_Chunk::fill_data_block (char * data_start) +{ + strncpy (data_start, identifier, 8); + + data_start += 8; + + *(int *) data_start = chunk_size; + + data_start += 4; + + *(int*)data_start = version_num; + *(int*)(data_start+4) = flags; + *(int*)(data_start+8) = reserved1; + *(int*)(data_start+12) = reserved2; + *(int*)(data_start+16) = reserved3; + *(int*)(data_start+20) = pplist.size(); + + data_start += 24; + + for (LIF li(&pplist); !li.done(); li.next()) + { + Preset_Palette current(li()); + + current.fill_data_block(data_start); + data_start += current.size_chunk(); + } +} + + +/////////////////////////////////////// + +// Class Environment_TLT_Chunk functions + + +RIF_IMPLEMENT_DYNCREATE("ENVTXLIT",Environment_TLT_Chunk) + +Environment_TLT_Chunk::Environment_TLT_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize) +: Chunk (parent, "ENVTXLIT"), width (*((int*)(sdata))), + num_levels (*((int*)(sdata+4))), flags(*(int *)(sdata+28)), table (0), filename(0) +{ + for (int i=0; i= 32 + width*num_levels) + { + table = new unsigned char [width*num_levels]; + unsigned char * tableptr = table; + unsigned char const * sdataptr = (unsigned char *)(sdata+32); + for (i=width*num_levels; i; --i) + { + *tableptr++ = *sdataptr++; + } + } + +} + +Environment_TLT_Chunk::~Environment_TLT_Chunk () +{ + if (table) delete[] table; + if (filename) delete[] filename; +} + +size_t Environment_TLT_Chunk::size_chunk() +{ + if (flags & ChunkTLTFlag_ExternalFile) + { + if (filename) + { + chunk_size = 12 + 32 + (strlen(filename)+4 & ~3); + } + else + { + chunk_size = 12 + 32 + 4; + } + } + else + { + chunk_size = 12 + 32 + width * num_levels; + } + return(chunk_size); + +} + +void Environment_TLT_Chunk::fill_data_block (char * data_start) +{ + strncpy (data_start, identifier, 8); + + data_start += 8; + + *((int *) data_start) = chunk_size; + + data_start += 4; + + *((int*)data_start) = width; + *((int*)(data_start+4)) = num_levels; + + data_start += 8; + + for (int i=0; i < ChunkTLT_NumReserved ; ++i, data_start+=4) + *((int *)data_start) = reserved[i]; + + *(int *)data_start = flags; + data_start+=4; + + if (flags & ChunkTLTFlag_ExternalFile) + { + if (filename) + strcpy(data_start,filename); + else + *data_start = 0; + } + else + { + if (table) + { + unsigned char * tableptr = table; + + for (i=width*num_levels; i; --i) + { + *data_start++ = *tableptr++; + } + } + else + { + for (i=width*num_levels; i; --i) + { + *data_start++ = 0; + } + } + } +} + + +/////////////////////////////////////// + +// Class TLT_Config_Chunk functions + +TLTCC_Flags::TLTCC_Flags(unsigned int data) +: allow_v2 (data & 0x00000001 ? 1 : 0) +, nodefault (data & 0x00000002 ? 1 : 0) +{ +} + +TLTCC_Flags::operator unsigned int () const +{ + return + allow_v2 * 0x00000001 + + nodefault * 0x00000002 ; +} + +RIF_IMPLEMENT_DYNCREATE("TLTCONFG",TLT_Config_Chunk) + +TLT_Config_Chunk::TLT_Config_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize) +: Chunk (parent, "TLTCONFG") +, num_shades_white(*(unsigned int const *)sdata) +, table_size(*(unsigned int const *)(sdata+4)) +, flags(*(unsigned int const *)(sdata+8)) +, palette_size(*(unsigned int const *)(sdata+12)) +{ + if (!table_size) table_size = 256; + + sdata+=16; + + for (int i=0; i<3; ++i, sdata+=4) reserved[i] = *(int *)sdata; + + unsigned int const len = strlen(sdata)+4&~3; + srcrifname = new char[len]; + memcpy(srcrifname,sdata,len); + sdata += len; + + unsigned int listsize = *(int *)sdata; + sdata += 4; + + while (listsize) + { + TLTConfigBlock block(sdata); + sdata += block.Size(); + blocks.add_entry_end(block); + listsize--; + } + + // hmm, size_chunk was wrong so allow sizes which were wrong in that way to pass + assert (ssize + 12 == size_chunk() || ssize + 12 + (44+strlen(srcrifname)+4&~3) - (44+strlen(srcrifname)+4&~4) == size_chunk()); +} + +size_t TLT_Config_Chunk::size_chunk() +{ + chunk_size = 44 + (srcrifname ? strlen(srcrifname) : 0) + 4 &~3; + for (LIF tbli(&blocks); !tbli.done(); tbli.next()) + { + chunk_size += tbli().Size(); + } + return chunk_size; +} + +void TLT_Config_Chunk::fill_data_block (char * data_start) +{ + strncpy (data_start, identifier, 8); + data_start += 8; + + *((int *) data_start) = chunk_size; + data_start += 4; + + *(unsigned int *)data_start = num_shades_white; + data_start += 4; + + *(unsigned int *)data_start = table_size; + data_start += 4; + + *(unsigned int *)data_start = flags; + data_start += 4; + + *(unsigned int *)data_start = palette_size; + data_start += 4; + + for (int i=0; i<3 ; ++i, data_start+=4) + *(int *)data_start = reserved[i]; + + strcpy(data_start,srcrifname ? srcrifname : ""); + + data_start += strlen(data_start) + 4 &~3; + + *(int *)data_start = blocks.size(); + data_start+=4; + + for (LIF tbli(&blocks); !tbli.done(); tbli.next()) + { + tbli().WriteData(data_start); + data_start += tbli().Size(); + } +} + + +/////////////////////////////////////// + +// Class Environment_Data_Chunk functions + +// constructor from buffer + +RIF_IMPLEMENT_DYNCREATE("GAMEMODE",Environment_Game_Mode_Chunk) + +/* +Children For Environment_Game_Mode_Chunk : + + +"GMODHEAD" Environment_Game_Mode_Header_Chunk +"ENVPALET" Environment_Palette_Chunk +"ENVTXLIT" Environment_TLT_Chunk +"TLTCONFG" TLT_Config_Chunk +"CLRLOOKP" Coloured_Polygons_Lookup_Chunk +"MATCHIMG" Matching_Images_Chunk +"SHBMPNAM" External_Shape_BMPs_Store_Chunk +"RIFCHILD" RIF_Child_Chunk +"SETPALST" Preset_Palette_Store_Chunk +"BMPMD5ID" Bitmap_MD5_Chunk +*/ + + +Environment_Game_Mode_Chunk::Environment_Game_Mode_Chunk(Chunk_With_Children* const parent,const char* data,size_t const size) +:Chunk_With_Children(parent,"GAMEMODE") , envd_parent((Environment_Data_Chunk *)parent) +{ + const char * buffer_ptr = data; + while ((data-buffer_ptr)< (signed) size) { + if ((*(int *)(data + 8)) + (data-buffer_ptr) > (signed) size) { + Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED; + break; + } + + DynCreate(data); + data += *(int *)(data + 8); + } +} + +char * Environment_Game_Mode_Chunk::ExpandedIdentifier() const +{ + char const * full_fname = header->flags & GameModeFlag_Editable ? ((File_Chunk *)GetRootChunk())->filename : header->get_safe_source(); + char const * skip = strrchr(full_fname,'\\'); + if (skip) full_fname = skip+1; + skip = strrchr(full_fname,'/'); + if (skip) full_fname = skip+1; + skip = strrchr(full_fname,':'); + if (skip) full_fname = skip+1; + char * retp = new char[strlen(full_fname)+strlen(header->mode_identifier)+3]; + strcpy(retp,full_fname); + char * dotpos = strrchr(retp,'.'); + if (dotpos) *dotpos = 0; + strcat(retp,"::"); + strcat(retp,header->mode_identifier); + return retp; +} + +// header chunk +RIF_IMPLEMENT_DYNCREATE("GMODHEAD",Environment_Game_Mode_Header_Chunk) + +Environment_Game_Mode_Header_Chunk::Environment_Game_Mode_Header_Chunk(Chunk_With_Children * const parent, const char * pdata, size_t const /*psize*/) +: Chunk (parent, "GMODHEAD"), flags(0), rif_files() +{ + flags = *((int *) pdata); + + pdata+=4; + + for (int i=0; iheader = this; +} + + +Environment_Game_Mode_Header_Chunk::~Environment_Game_Mode_Header_Chunk() +{ + if (mode_identifier) delete[] mode_identifier; + + while (rif_files.size()) + { + delete [] rif_files.first_entry(); + rif_files.delete_first_entry(); + } +} + + + +void Environment_Game_Mode_Header_Chunk::fill_data_block ( char * data_start) +{ + strncpy (data_start, identifier, 8); + + data_start += 8; + + *((int *) data_start) = chunk_size; + + data_start += 4; + + *((int *) data_start) = flags; + data_start+=4; + + for (int i=0; i li(&rif_files); !li.done(); li.next()) + { + strcpy(data_start,li()); + + data_start += strlen(li())+1; + } + + *data_start = 0; // double 0-byte terminator +} + + +size_t Environment_Game_Mode_Header_Chunk::size_chunk () +{ + chunk_size = 12+20+(strlen(mode_identifier)+1); + + for (LIF li(&rif_files); !li.done(); li.next()) + { + chunk_size += strlen(li())+1; + } + + chunk_size += 4; // 1 byte terminator, 3(max) to pad + chunk_size &= ~3; + return chunk_size; +} + + + +//////////////////////////////////////// + +// Class RIF_Child_Chunk - for RIFs in game modes containing graphics +RIF_IMPLEMENT_DYNCREATE("RIFCHILD",RIF_Child_Chunk) + +RIF_Child_Chunk::~RIF_Child_Chunk() +{ + if (filename) delete[] filename; + if (rifname) delete[] rifname; +} + +size_t RIF_Child_Chunk::size_chunk() +{ + chunk_size = 12 + 12 + (strlen(rifname)+1 +3 &~3) + 4 + (strlen(filename)+1 +3 &~3) + 4; + + for (LIF li(&bmps); !li.done(); li.next()) + { + chunk_size += 8 + strlen(li().filename)+1 +3 & ~3; + } + + return chunk_size; +} + +void RIF_Child_Chunk::fill_data_block(char * data_start) +{ + strncpy (data_start, identifier, 8); + + data_start += 8; + + *((int *) data_start) = chunk_size; + + data_start += 4; + + for (int i=0; i li(&bmps); !li.done(); li.next()) + { + *((int *) data_start) = li().flags; + data_start += 4; + *((int *) data_start) = li().version_num & BMPFLAGS_VERSION_NUM_MASK | li().enum_id << BMPFLAGS_ENUMID_SHIFT; + data_start += 4; + + strcpy(data_start, li().filename); + data_start += strlen(li().filename)+1 +3 &~3; + } + +} + +int const * RIF_Child_Chunk::GetMD5Val(BMP_Flags const & rcbmp) +{ + Bitmap_MD5_Chunk * md5c = GetMD5Chunk(rcbmp.filename); + if (md5c) + if (rcbmp.version_num == md5c->version_num) + return md5c->md5_val; + return 0; +} + +void RIF_Child_Chunk::RemoveMD5Val(char const * bname) +{ + Bitmap_MD5_Chunk * md5c = GetMD5Chunk(bname); + if (md5c) + delete md5c; +} + +void RIF_Child_Chunk::SetMD5Val(BMP_Flags const & rcbmp, int const * md5id) +{ + Bitmap_MD5_Chunk * md5c = GetMD5Chunk(rcbmp.filename); + if (md5c) + { + if (rcbmp.version_num == md5c->version_num) + { + memcpy(md5c->md5_val,md5id,16); + return; + } + else + delete md5c; + } + CreateMD5Chunk(rcbmp,md5id); +} + +Bitmap_MD5_Chunk * RIF_Child_Chunk::GetMD5Chunk(char const * bname) +{ + List chlst; + parent->lookup_child("BMPMD5ID",chlst); + + for (LIF i_chlst(&chlst); !i_chlst.done(); i_chlst.next()) + { + Bitmap_MD5_Chunk * md5c = (Bitmap_MD5_Chunk *)i_chlst(); + + if (!strcmp(md5c->bmpname,bname)) + if (!(md5c->rifname ? rifname ? strcmp(rifname,md5c->rifname) : *md5c->rifname : rifname ? *rifname : 0) && + !(md5c->shapename ? *md5c->shapename : 1)) + return md5c; + } + + return 0; +} + +void RIF_Child_Chunk::CreateMD5Chunk(BMP_Flags const & rcbmp, int const * md5id) +{ + new Bitmap_MD5_Chunk(parent,md5id,rcbmp,rifname); +} + +RIF_Child_Chunk::RIF_Child_Chunk (Chunk_With_Children * const parent, const char * sdata, size_t const /*ssize*/) +: Chunk(parent,"RIFCHILD"), egm_parent((Environment_Game_Mode_Chunk * const)parent) +{ + for (int i=0; i> BMPFLAGS_ENUMID_SHIFT); + temp.version_num = *(int *)sdata & BMPFLAGS_VERSION_NUM_MASK; + sdata += 4; + + len = strlen(sdata)+1; + temp.filename = new char[len]; + strcpy(temp.filename,sdata); + sdata += len+3 &~3; + + bmps.add_entry(temp); + } + +} + +///////////////////////////////// +// Preset_Palette_Store_Chunk +// ties in with RIF_Child_Chunk +// the filenames (-dirname) should match + +RIF_IMPLEMENT_DYNCREATE("SETPALST",Preset_Palette_Store_Chunk) + +Preset_Palette_Store_Chunk::Preset_Palette_Store_Chunk(Chunk_With_Children * const parent, char const * sdata, size_t const /*ssize*/) +: Chunk(parent,"SETPALST") +, version_num(*(int *)sdata) +, flags(*(int *)(sdata+4)) +, reserved1(*(int *)(sdata+8)) +, reserved2(*(int *)(sdata+12)) +, reserved3(*(int *)(sdata+16)) +{ + sdata += 20; + + unsigned int const len = strlen(sdata)+1; + rifname = new char[len]; + strcpy(rifname,sdata); + sdata += len + 3 &~3; + + int const pplistsize = *(int *)sdata; + sdata += 4; + + for (int i = pplistsize; i; --i) + { + Preset_Palette current(sdata); + sdata += current.size_chunk(); + pplist.add_entry(current); + } +} + + +size_t Preset_Palette_Store_Chunk::size_chunk () +{ + chunk_size = 12 + 24 + strlen(rifname)+1+3 &~3; + + for (LIF li(&pplist); !li.done(); li.next()) + { + chunk_size += li().size_chunk(); + } + + return chunk_size; +} + +void Preset_Palette_Store_Chunk::fill_data_block (char * data_start) +{ + strncpy (data_start, identifier, 8); + + data_start += 8; + + *(int *) data_start = chunk_size; + + data_start += 4; + + *(int*)data_start = version_num; + *(int*)(data_start+4) = flags; + *(int*)(data_start+8) = reserved1; + *(int*)(data_start+12) = reserved2; + *(int*)(data_start+16) = reserved3; + data_start += 20; + + strcpy(data_start,rifname); + data_start+=strlen(rifname)+1+3 &~3; + + *(int*)(data_start) = pplist.size(); + data_start += 4; + + for (LIF li(&pplist); !li.done(); li.next()) + { + Preset_Palette current(li()); + + current.fill_data_block(data_start); + data_start += current.size_chunk(); + } +} + + + + + +/////////////////////////////////////// + +// Class Coloured_Polygons_Lookup_Chunk functions + +// simple 32K tables for palettes to quickly map coloured +// polygons to the right palette colour on loading, with 15-bit definition + + +RIF_IMPLEMENT_DYNCREATE("CLRLOOKP",Coloured_Polygons_Lookup_Chunk) + +Coloured_Polygons_Lookup_Chunk::Coloured_Polygons_Lookup_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/) +: Chunk (parent, "CLRLOOKP"), flags (*((int*)(sdata))), + filename(0), table (0) +{ + for (int i=0; i