#ifndef _included_chunkpal_hpp_ #define _included_chunkpal_hpp_ #include "chunk.hpp" #include "bmpnames.hpp" #if cencon #include "palette.h" #endif static const unsigned char * grab_pixel_data(int ssize, unsigned char const * sdata) { if (!ssize) return 0; ssize *= 3; unsigned char * pixels = new unsigned char[ssize]; unsigned char * ddata = pixels; for (int cnt = ssize; cnt; --cnt, ++ddata, ++sdata) *ddata = *sdata; return pixels; } class Environment_Palette_Chunk : public Chunk { public: #if cencon // constructor from data - defined in genpal Environment_Palette_Chunk (Chunk_With_Children * const parent, PPM_Header const * const palette); #endif // constructor from buffer Environment_Palette_Chunk (Chunk_With_Children * const parent, const char * sdata, size_t const /*ssize*/) : Chunk (parent, "ENVPALET") , width (*(int *)sdata) , height (1) , flags (*(int *)(sdata+4)) , pixel_data (grab_pixel_data(*(int *)sdata,(unsigned char *)(sdata+8))) {} ~Environment_Palette_Chunk (); virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); const int width; const int height; int flags; // was width, but width was always 1 // do not use as a flag 0x00000001 #define EnvPalFlag_UpToDate 0x00000002 // make flag #define EnvPalFlag_Lit 0x00000004 // uses darken flag when generating palette #define EnvPalFlag_V2 0x00000008 // flagged to distinguish between big tlt palette & normal palette #define DEFAULT_ENV_PAL_FLAGS EnvPalFlag_Lit const unsigned char * const pixel_data; private: friend class Environment_Data_Chunk; friend class Environment_Game_Mode_Chunk; }; class Preset_Palette_Chunk; class Preset_Palette { public: #if cencon // constructor from data - defined in genpal Preset_Palette (PPM_Header const * const palette); // update by generating from bmps chunk void update(Global_BMP_Name_Chunk * gbnc, Preset_Palette_Chunk * ppc, class Environment * e, Environment_Data_Chunk * envd, BOOL bDoSoftwareTex); #if 0 Preset_Palette (const char * iname) : size(0) , flags(0) , reserved1(0) , reserved2(0) , startpos(0) , pixel_data(0) , name(0) { if (iname) { name = new char[strlen(iname)+1]; strcpy(name,iname); } } #endif #endif Preset_Palette () : size(0) , flags(0) , reserved1(0) , reserved2(0) , startpos(0) , pixel_data(0) , name(0) {} // copy constructor Preset_Palette (Preset_Palette const & c); ~Preset_Palette (); Preset_Palette & operator = (Preset_Palette const & c); const int size; int flags; #define PrePalFlag_Reserved 0x00000001 // preset palette defines contant entries in palette for graphics which are not reloaded #define PrePalFlag_UpToDate 0x00000002 #define PrePalFlag_V2 0x00000004 // calculated fixed palette using wide palette, tlt and lit textures const int reserved1; const int reserved2; int startpos; char * name; const unsigned char * const pixel_data; // for the list template inline BOOL operator == (Preset_Palette const & c) const { return !_stricmp(name,c.name); } inline BOOL operator != (Preset_Palette const & c) const { return _stricmp(name,c.name); } inline BOOL operator < (Preset_Palette const & c) const { return startpos < c.startpos; } private: friend class Preset_Palette_Chunk; friend class Preset_Palette_Store_Chunk; size_t size_chunk () const; void fill_data_block (char * data_start); // constructor from buffer Preset_Palette (char const * sdata) : size (*(int *)sdata) , flags (*(int *)(sdata+4)) , reserved1 (*(int *)(sdata+8)) , reserved2 (*(int *)(sdata+12)) , startpos (*(int *)(sdata+16)) , pixel_data (grab_pixel_data(*(int *)sdata,(unsigned char *)(sdata+20))) { sdata += 20+size*3; name = new char[strlen(sdata)+1]; strcpy(name,sdata); } }; class Preset_Palette_Chunk : public Chunk { public: #if cencon // empty constructor Preset_Palette_Chunk (Chunk_With_Children * const parent) : Chunk (parent,"PRSETPAL") , flags(0) , version_num(0) , reserved1(0) , reserved2(0) , reserved3(0) {} #endif // constructor from buffer Preset_Palette_Chunk (Chunk_With_Children * const parent, char const * sdata, size_t const ssize); ~Preset_Palette_Chunk () {}; virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); int flags; int version_num; const int reserved1; const int reserved2; const int reserved3; List pplist; private: friend class Environment_Data_Chunk; }; class Environment_TLT_Chunk : public Chunk { public: #if cencon // constructor using palette - defined in genpal Environment_TLT_Chunk (Chunk_With_Children * parent, PPM_Header * palette, PPM_Header * tlt_palette, Lighting_Style const * ls); #endif // constructor from buffer Environment_TLT_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize); ~Environment_TLT_Chunk (); virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); int width; // should be == palette size, though may well have to be 256 due to the way 3dc lookup works int num_levels; // usually 256, for 256 "different" shades of each colour #define ChunkTLT_NumReserved 5 int reserved[ ChunkTLT_NumReserved ]; int flags; // either expect filename or table #define ChunkTLTFlag_ExternalFile 0x00000001 #define ChunkTLTFlag_OptionsChanged 0x00000002 #define ChunkTLTFlag_V2 0x00000004 // version 2: may have width != 256, flagged so we can distinguish between two tables in chunk char * filename; // either a filename unsigned char * table; // or an actual table in memory private: friend class Environment_Data_Chunk; friend class Environment_Game_Mode_Chunk; }; class TLTConfigBlock { public: // constructos; TLTConfigBlock() { spares[0]=0; spares[1]=0; spares[2]=0; spares[3]=0; } TLTConfigBlock(double const & iistart, double const & oistart, double const & iiend, double const & oiend) : input_intensity_start(iistart) , output_intensity_start(oistart) , input_intensity_end(iiend) , output_intensity_end(oiend) { spares[0]=0; spares[1]=0; spares[2]=0; spares[3]=0; } // I/O TLTConfigBlock(char const * datablock) : input_intensity_start(*(double *)datablock) , output_intensity_start(*(double *)(datablock+8)) , input_intensity_end(*(double *)(datablock+16)) , output_intensity_end(*(double *)(datablock+24)) { memcpy(spares,datablock+32,16); } inline size_t Size() const { return 48; } inline void WriteData(char * datablock) const { *(double *)datablock = input_intensity_start; datablock += 8; *(double *)datablock = output_intensity_start; datablock += 8; *(double *)datablock = input_intensity_end; datablock += 8; *(double *)datablock = output_intensity_end; datablock += 8; memcpy(datablock,spares,16); } // operators inline BOOL operator == (TLTConfigBlock const & tcb2) const { return input_intensity_start == tcb2.input_intensity_start && output_intensity_start == tcb2.output_intensity_start && input_intensity_end == tcb2.input_intensity_end && output_intensity_end == tcb2.output_intensity_end; } inline BOOL operator != (TLTConfigBlock const & tcb2) const { return ! operator == (tcb2); } // members double input_intensity_start; double output_intensity_start; double input_intensity_end; double output_intensity_end; private: int spares[4]; }; struct TLTCC_Flags { TLTCC_Flags(unsigned int data = 0); operator unsigned int () const; unsigned int allow_v2 : 1; // palette size refers to bigger size table unsigned int nodefault : 1; // suppress normal 256 colour tlts }; class TLT_Config_Chunk : public Chunk { public: #if cencon // constructor for default TLT_Config_Chunk (Chunk_With_Children * parent, char const * rifname = 0) : Chunk (parent, "TLTCONFG") , num_shades_white(16) , srcrifname(rifname ? new char [strlen(rifname)+1] : 0) , blocks(TLTConfigBlock(0,0,1,1)) , table_size(256) , palette_size(0) { for (int i=0; i<3; ++i) reserved[i]=0; if (rifname) strcpy(srcrifname,rifname); } #endif // constructor from buffer TLT_Config_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize); ~TLT_Config_Chunk() { if (srcrifname) delete[] srcrifname; } virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); char * srcrifname; unsigned int num_shades_white; unsigned int table_size; List blocks; unsigned int palette_size; // for version 2 palettes and big tlt TLTCC_Flags flags; inline BOOL operator == (TLT_Config_Chunk const & tcc2) const { return blocks == tcc2.blocks && num_shades_white == tcc2.num_shades_white && table_size == tcc2.table_size && flags == tcc2.flags && (!flags.allow_v2 || palette_size == tcc2.palette_size); } inline BOOL operator != (TLT_Config_Chunk const & tcc2) const { return ! operator == (tcc2); } inline BOOL NeedFullRemake(TLT_Config_Chunk const & tcc_old) const { return blocks != tcc_old.blocks || num_shades_white != tcc_old.num_shades_white; } inline BOOL NeedNewTLTPalette(TLT_Config_Chunk const & tcc_old) const { return flags != tcc_old.flags || flags.allow_v2 && palette_size != tcc_old.palette_size; } private: int reserved[3]; friend class Environment_Data_Chunk; friend class Environment_Game_Mode_Chunk; }; #if cencon extern TLT_Config_Chunk Default_TLT_Config_Chunk; #endif // Multi-Palettes for one environment // Coloured polygons will be set on load-up // If 15 bit is good-enough, we can use a 32K // lookup table for the coloured polygons, // otherwise we'll have to do the slower // distance comparisons // We need a new chunk which is a child of the REBENVDT environment data chunk // this will be a GAMEMODE chunk with children, and there may be more than one // in the case where there are several palettes available for the environment // there will be an identifying string in the gamepalette chunk. // the "REBENVDT"->lookup_child("GAMPALET") will return a list of these chunks, // so you can look through them to find the one you want // There should be some sort of convention/restriction/communication // about the // most of the information will be in its children, which can be any of the following // ENVPALET // RIFCHILD(s) - the name of RIF file(s) // this is basically a RIF_Name_Chunk, but named differently so as to distinguish it from its own file's name // which should have a REBENVDT chunk with BMPNAMES and/or RIFCHILD(s) (even more RIFs) // specifying what non-environment specific bitmaps are used, and probably much more data, // - they could be sprites, etc. // then all the data could be automatically included (but not loaded) by the inclusion of one file // ENVTXLIT - texture lighting table, // but maybe this should a filename to load if required // CLRLOOKP - 15-bit r;g;b lookup table to get palette entries for coloured polygons on load // can have a table or a reference file // other relevant chunks to be added later // we may need some sort of BMPNAMES chunk, for flags about which bmps are quantized, etc. // HOW TO USE - example (supplied without warranty) // ---------- /* File_Chunk * environment = $current environment$; List envdatalist = environment->lookup_child("REBENVDT"); if (envdatalist.size()) { Environment_Data_Chunk * envdata = (Environment_Data_Chunk *)envdatalist.first_entry(); List gamemodelist = envdata->lookup_child("GAMEMODE"); Environment_Game_Mode_Chunk * selected = 0; for(LIF li(&gamemodelist); !li.done(); li.next()) { Environment_Game_Mode_Chunk * try_this = (Environment_Game_Mode_Chunk *) li(); if (try_this->id_equals((const char *)$your identifier$)) { selected = try_this; break; } } if (selected) { List bmpgrouplist = selected->lookup_child("RIFCHILD"); String subdir; List rifnamechunk = envdata->lookup_child("RIFFNAME"); if (rifnamechunk.size()) subdir = ((RIF_Name_Chunk *) rifnamechunk.first_entry())->rif_name; else subdir = "empty"; // load graphics loop for (LIF g(&bmpgrouplist); !g.done(); g.next()) { RIF_Child_Chunk * current = (RIF_Child_Chunk *)g(); const char * mipmap_0; const char * mipmap_n; String dir; if ($loading pgms$) { dir = (String)"Game-Textures\\" + subdir + "\\" + (String)$your identifier$ + "\\"; if (*current->filename) { dir += (String)current->rifname + "\\"; } mipmap_0 = ".pg0"; mipmap_n = ".pg%1d"; } else // loading bm0 to bm6 { dir = (String)"Generic-Textures\\" + current->rifname + "\\"; mipmap_0 = ".pg0"; mipmap_n = ".pg%1d"; } // load graphics-set loop for (LIF img(¤t->bmps); !img.done(); img.next()) { BMP_Flags bmp = img(); char * imname = new char[strlen(bmp.filename)+5]; strcpy(imname,bmp.filename); char * dotpos = strrchr(imname,'.'); if (!dotpos) dotpos = imname + strlen(imname); strcpy(dotpos,mipmap_0); String filename = dir + imname; $load image$(filename) if (bmp.flags & ChunkBMPFlag_MipMapsQuantized) { // load mipmaps loop for (int i = 1 ; i<=6 ; ++i) { sprintf(dotpos,mipmap_n,i); filename = dir + imname; $load image$(filename) } } delete [] imname; } } } else { // your identifier is not valid } } else { // no data } */ #define GameModeFlag_Editable 0x00000001 // game modes are not editable if they are included from another RIF #define GameModeFlag_Deleted 0x00000002 // so you can click on cancel and invisibly no updating will be done #define GameModeFlag_Added 0x00000004 // ditto class Environment_Game_Mode_Chunk; class Environment_Game_Mode_Header_Chunk; class Environment_Game_Mode_Chunk : public Chunk_With_Children { public: #if cencon // constructor from data Environment_Game_Mode_Chunk (Environment_Data_Chunk * const parent, const char * _mode_id); // defined in gmodlink void remove(class CWnd * const pWnd); // update this copy by finding its original void update(class CWnd * const pWnd, BOOL bDoSoftwareTex); // update this copy by finding its original void been_updated(class CWnd * const pWnd, BOOL bDoSoftwareTex); // find and update copies from this original void definite_update(Environment_Game_Mode_Chunk const * const src, class CWnd * const pWnd, Environment_Data_Chunk * envd, BOOL bDoSoftwareTex); #endif // constructor from buffer Environment_Game_Mode_Chunk (Chunk_With_Children * const parent, const char * sdata, size_t const ssize); ~Environment_Game_Mode_Chunk(){} Environment_Game_Mode_Header_Chunk * header; Environment_Data_Chunk * const envd_parent; char * ExpandedIdentifier() const; // must delete return value inline BOOL operator == (Environment_Game_Mode_Chunk const & m) const; inline BOOL operator != (Environment_Game_Mode_Chunk const & m) const; // public function for people to check if they have the game mode they want inline BOOL id_equals(const char * s) const; private: friend class Environment_Data_Chunk; }; class Environment_Game_Mode_Chunk_Pointer { private: Environment_Game_Mode_Chunk * p; // poor lonely thing has no friends and never will -- aaaahh private: inline Environment_Game_Mode_Chunk_Pointer(void) : p(0) {}; friend struct List_Member; public: // copy constructor from another of this type //inline Environment_Game_Mode_Chunk_Pointer(Environment_Game_Mode_Chunk_Pointer const & cp) : p(cp.p) {}; // cast constructor from C pointer inline Environment_Game_Mode_Chunk_Pointer(Environment_Game_Mode_Chunk * const cp) : p(cp) {}; // cast to C pointer operator inline operator Environment_Game_Mode_Chunk * (void) const { return p; } // no empty constructor -- p must always be valid // equavalence based on contents of pointer, not addresses being the same inline BOOL operator == (Environment_Game_Mode_Chunk_Pointer const m) const { if (!p || !m.p) return 0; return *p == *m.p; } inline BOOL operator != (Environment_Game_Mode_Chunk_Pointer const m) const { if (!p || !m.p) return 1; return *p != *m.p; } }; /////////////////////////////////////////////// class Environment_Game_Mode_Header_Chunk : public Chunk { public: // constructor from buffer Environment_Game_Mode_Header_Chunk (Chunk_With_Children * const parent, const char * pdata, size_t const psize); virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); inline BOOL id_equals(const char * s) { if (_stricmp(s,mode_identifier)) return FALSE; else return TRUE; } int flags; char * mode_identifier; inline void add_rif_entry(char const * f) { char * n = new char[strlen(f)+1]; strcpy(n,f); rif_files.add_entry(n); } inline const char * get_safe_source(void) { if (flags & GameModeFlag_Editable) return "this.rif"; if (!rif_files.size()) return "unknown.rif"; return rif_files.first_entry(); } private: friend class Environment_Game_Mode_Chunk; friend class Cwm_GAMEMODEDlg; friend class Cwm_GAMEMODClicked116Dlg; friend class GameModeDlg; friend class GameModeRifDlg; List rif_files; // where the game mode goes to or comes from #define ChunkGMod_NumReserved 3 int reserved[ChunkGMod_NumReserved]; int version_num; #if cencon // constructor from parent Environment_Game_Mode_Header_Chunk (Environment_Game_Mode_Chunk * const parent, const char * const _mode_id) : Chunk (parent, "GMODHEAD"), version_num(0), flags (0), rif_files() { for (int i=0; iheader = this; } inline Environment_Game_Mode_Header_Chunk const & operator = (Environment_Game_Mode_Header_Chunk & s) { flags = s.flags; while (rif_files.size()) { delete[] rif_files.first_entry(); rif_files.delete_first_entry(); } if (mode_identifier) delete[] mode_identifier; mode_identifier = new char[strlen(s.mode_identifier)+1]; strcpy(mode_identifier,s.mode_identifier); for (LIF src(&s.rif_files); !src.done(); src.next()) { add_rif_entry(src()); } version_num = s.version_num; return *this; } #endif // deconstructor ~Environment_Game_Mode_Header_Chunk(); }; ////////////////// inline BOOL Environment_Game_Mode_Chunk::operator == (Environment_Game_Mode_Chunk const & m) const { if ((header->flags | m.header->flags) & GameModeFlag_Deleted) return FALSE; return !_stricmp(header->mode_identifier,m.header->mode_identifier); } inline BOOL Environment_Game_Mode_Chunk::operator != (Environment_Game_Mode_Chunk const & m) const { if ((header->flags | m.header->flags) & GameModeFlag_Deleted) return TRUE; return _stricmp(header->mode_identifier,m.header->mode_identifier); } inline BOOL Environment_Game_Mode_Chunk::id_equals(const char * s) const { return header->id_equals(s); } /////////////////////////////////////////////// class RIF_Child_Chunk; class BMP_Flags { public: BMP_Flags(void) : filename(0), enum_id(0), version_num(0), flags((BMPN_Flags)0){} BMP_Flags(const char * const fname) : enum_id(0), version_num(0), flags((BMPN_Flags)0), filename(0) { if (fname) { filename = new char[strlen(fname)+1]; strcpy(filename,fname); } } BMP_Flags(BMP_Name const & bn) : enum_id(bn.enum_id), version_num(bn.version_num), flags((BMPN_Flags)(bn.flags & COPY_BMPN_FLAGS)), filename(0) { if (bn.filename) { filename = new char[strlen(bn.filename)+1]; strcpy(filename,bn.filename); } } BMP_Flags(BMP_Flags const & c) : filename(0), enum_id(c.enum_id), version_num(c.version_num), flags(c.flags) { if (c.filename) { filename = new char[strlen(c.filename)+1]; strcpy(filename,c.filename); } } operator BMP_Name () const { BMP_Name cast(filename); cast.flags = flags; cast.version_num = version_num; cast.enum_id = enum_id; return cast; } ~BMP_Flags() { if (filename) delete[] filename; } BMP_Flags & operator = (BMP_Flags const & c) { if (filename) delete[] filename; if (c.filename) { filename = new char[strlen(c.filename)+1]; strcpy(filename,c.filename); } else filename = 0; flags = c.flags; version_num = c.version_num; enum_id = c.enum_id; return *this; } char * filename; BMPN_Flags flags; #define BMPFLAGS_VERSION_NUM_MASK 0x000fffff #define BMPFLAGS_ENUMID_SHIFT 20 int version_num; int enum_id; inline BOOL operator == (BMP_Flags const & c) const { return !_stricmp(filename,c.filename); } inline BOOL operator != (BMP_Flags const & c) const { return _stricmp(filename,c.filename); } #if cencon void DeleteAssociatedFiles(RIF_Child_Chunk const *, Environment_Data_Chunk *) const; #endif }; enum RCC_Flags { RCCF_EXTERNSHAPE = 0x00000001, // bitmaps from shape which is in game mode solely because it was an external shape added to the environment with this game mode RCCF_FIXEDPALETTE = 0x00000002, // pgms are quantized with a fixed constant palette RCCF_HISTOGRAMEXISTS = 0x00000004, RCCF_HISTOGRAMV2EXISTS = 0x00000008, RCCF_DEFAULT = 0 }; class RIF_Child_Chunk : public Chunk { public: #if cencon RIF_Child_Chunk(Environment_Game_Mode_Chunk * const parent, const char * fname, class CWnd * const pWnd, BOOL bDoSoftwareTex); void update(class CWnd * const, BOOL bDoSoftwareTex); void update(class Environment * e, BOOL bDoSoftwareTex); // for where the environment is already loaded void DeleteAssociatedFiles(Environment_Data_Chunk *) const; #endif // constructor from buffer RIF_Child_Chunk (Chunk_With_Children * const parent, const char * sdata, size_t const ssize); ~RIF_Child_Chunk(); virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); int const * GetMD5Val(BMP_Flags const & rcbmp); void SetMD5Val(BMP_Flags const & rcbmp, int const * md5id); void RemoveMD5Val(char const * bname); Bitmap_MD5_Chunk * GetMD5Chunk(char const * bname); void CreateMD5Chunk(BMP_Flags const & rcbmp, int const * md5id); Environment_Game_Mode_Chunk * const egm_parent; int version_num; char * filename; char * rifname; inline BOOL operator == (RIF_Child_Chunk const & c) const { return !strcmp(rifname,c.rifname); } inline BOOL operator != (RIF_Child_Chunk const & c) const { return strcmp(rifname,c.rifname); } List bmps; RCC_Flags flags; #define ChunkRIFChild_NumReserved 2 int reserved[ChunkRIFChild_NumReserved]; private: friend class Environment_Game_Mode_Chunk; }; class Preset_Palette_Store_Chunk : public Chunk { public: #if cencon // constructor from Preset_Palette_Chunk Preset_Palette_Store_Chunk (Chunk_With_Children * const parent, Preset_Palette_Chunk const * const schunk, const char * const srname) : Chunk (parent,"SETPALST") , flags(schunk->flags) , version_num(schunk->version_num) , reserved1(schunk->reserved1) , reserved2(schunk->reserved2) , reserved3(schunk->reserved3) , rifname(new char[strlen(srname)+1]) , pplist(schunk->pplist) { strcpy(rifname,srname); } // empty constructor Preset_Palette_Store_Chunk (Chunk_With_Children * const parent, const char * const srname) : Chunk (parent,"SETPALST") , flags(0) , version_num(0) , reserved1(0) , reserved2(0) , reserved3(0) , rifname(new char[strlen(srname)+1]) { strcpy(rifname,srname); } #endif // constructor from buffer Preset_Palette_Store_Chunk (Chunk_With_Children * const parent, char const * sdata, size_t const ssize); ~Preset_Palette_Store_Chunk () { if (rifname) delete[] rifname; } virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); int flags; int version_num; const int reserved1; const int reserved2; const int reserved3; char * rifname; inline BOOL operator == (Preset_Palette_Store_Chunk const & c) const { return !strcmp(rifname,c.rifname); } inline BOOL operator != (Preset_Palette_Store_Chunk const & c) const { return strcmp(rifname,c.rifname); } List pplist; private: friend class Environment_Game_Mode_Chunk; }; /////////////////////////////////////////////// class Coloured_Polygons_Lookup_Chunk : public Chunk { public: #if cencon // constructor from data - defined in cencon Coloured_Polygons_Lookup_Chunk (Chunk_With_Children * parent, PPM_Header * const palette); #endif // constructor from buffer Coloured_Polygons_Lookup_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize); ~Coloured_Polygons_Lookup_Chunk (); virtual size_t size_chunk (); virtual void fill_data_block (char * data_start); int flags; #define ChunkCPLUFlag_ExternalFile 0x00000001 #define ChunkCPLU_NumReserved 7 int reserved[ ChunkCPLU_NumReserved ]; char * filename; unsigned char * table; private: friend class Environment_Game_Mode_Chunk; friend class Environment_Data_Chunk; }; #endif // !included