#include #define TRY_OLD_DIRS 0 // obsolete #define ALLOW_LOAD_ORIGINAL 0 #if TRY_OLD_DIRS // temporary until all textures go into subshps directory #include "ffstdio.h" #endif #include "chnkimag.hpp" #include "list_tem.hpp" #include "envchunk.hpp" #include "chunkpal.hpp" #include "bmpnames.hpp" #include "chnkload.hpp" char const * CL_RIFFImage::game_mode = 0; // useful filename handling functions // returns pointer into string pointing to filename without dirname template // C can be char or char const static C * strip_path(C * n) { C * rm = strrchr(n,':'); if (rm) n = rm+1; rm = strrchr(n,'/'); if (rm) n = rm+1; rm = strrchr(n,'\\'); if (rm) n = rm+1; return n; } // removes any .extension from filename by inserting null character static void strip_file_extension(char * n) { char * dotpos = strrchr(n,'.'); if (dotpos) *dotpos = 0; } static char * strip_file_extension(char const * n) { char * nn = new char[strlen(n)+1]; strcpy(nn,n); strip_file_extension(nn); return nn; } //////////////////////// // // riff file interface // //////////////////////// // get the directory associated with the riff - free with delete[] static char * riff_basename(Chunk_With_Children * envd) { RIF_Name_Chunk * rnc = 0; List chlst = envd->lookup_child("RIFFNAME"); if (chlst.size()) { rnc = (RIF_Name_Chunk *)chlst.first_entry(); const char * rif_name = strip_path(rnc->rif_name); char * basename = new char[strlen(rif_name)+1]; strcpy(basename,rif_name); strip_file_extension(basename); return basename; } const char * deflt = "empty"; char * basename = new char [strlen(deflt)+1]; strcpy(basename,deflt); return basename; } #if OUTPUT_LOG #define _LOGID CL_LogFile.lprintf("%s:%d :: ",__FILE__,__LINE__) #define _LOGPUT(s) _LOGID,CL_LogFile.lputs(s) #define _LOGPRINT(args) _LOGID,CL_LogFile.lprintf args #else #define _LOGPUT(s) (void)0 #define _LOGPRINT(args) (void)0 #endif void CL_RIFFImage::GetPath(ImageDescriptor const & idsc, Environment_Data_Chunk * envd, BMPN_Flags bflags) { if (fname) delete[] fname; fname = 0; // set the name if (name) delete[] name; char * nptr = strip_path(idsc.filename); name = new char[strlen(nptr)+1]; strcpy(name,nptr); #if 0 char orig_ext[32]; char const * oeP = strrchr(name,'.'); if (!oeP) eoP = ""; strcpy(orig_ext,oeP); #endif strip_file_extension(name); // load this image char const * pg0ext = ".PG0"; switch (imode) { case CLM_16BIT: case CLM_24BIT: case CLM_32BIT: #if ALLOW_LOAD_ORIGINAL { char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : ""; char * riffname = riff_basename(envd); char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname; fname = new char[strlen(ToolsTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(name)+5]; strcpy(fname,ToolsTex_Directory); strcat(fname,dir2); strcat(fname,dir3); strcat(fname,"\\"); strcat(fname,name); strcat(fname,".PP0"); delete[] riffname; break; } #endif case CLM_ATTACHEDPALETTE: { char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : idsc.flags & IDSCF_SUBSHAPE ? "SubShps\\All\\" : ""; char * riffname = riff_basename(envd); char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname; fname = new char[strlen(GenTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(name)+5]; strcpy(fname,GenTex_Directory); strcat(fname,dir2); strcat(fname,dir3); strcat(fname,"\\"); strcat(fname,name); strcat(fname,".BM0"); delete[] riffname; #if TRY_OLD_DIRS // temporary until all textures go into subshps directory FFILE * ftest = ffopen(fname,"rb"); if (ftest) ffclose(ftest); else { _LOGPUT("WARNING! Not found in SubShps directory\n"); char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : ""; char * riffname = riff_basename(envd); char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname; delete[] fname; fname = new char[strlen(GenTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(name)+5]; strcpy(fname,GenTex_Directory); strcat(fname,dir2); strcat(fname,dir3); strcat(fname,"\\"); strcat(fname,name); strcat(fname,".BM0"); delete[] riffname; } #endif break; } case CLM_TLTPALETTE: if (!(bflags & ChunkBMPFlag_NotLit)) { pg0ext = ".PW0"; flags.tltpalette = 1; } case CLM_GLOBALPALETTE: { if (idsc.flags & IDSCF_FIXEDPALETTE) { char const * dir2 = idsc.fixrifname ? *idsc.fixrifname ? idsc.fixrifname : 0 : 0; char const * dir3 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : ""; char * riffname = riff_basename(envd); char const * dir4 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname; fname = new char[strlen(FixTex_Directory)+(dir2 ? strlen(dir2)+1 : 0)+strlen(dir3)+strlen(dir4)+1+strlen(name)+5]; strcpy(fname,FixTex_Directory); if (dir2) { strcat(fname,dir2); strcat(fname,"\\"); } strcat(fname,dir3); strcat(fname,dir4); strcat(fname,"\\"); strcat(fname,name); strcat(fname,pg0ext); delete[] riffname; } else { char const * dir1 = game_mode ? GameTex_Directory : ToolsTex_Directory; char * dir2 = riff_basename(envd); char const * dir4 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : ""; char const * dir5 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : 0; fname = new char[strlen(dir1)+strlen(dir2)+1+(game_mode ? strlen(game_mode)+1 : 0)+strlen(dir4)+(dir5 ? strlen(dir5)+1 : 0)+strlen(name)+5]; strcpy(fname,dir1); strcat(fname,dir2); strcat(fname,"\\"); if (game_mode) { strcat(fname,game_mode); strcat(fname,"\\"); } strcat(fname,dir4); if (dir5) { strcat(fname,dir5); strcat(fname,"\\"); } strcat(fname,name); strcat(fname,pg0ext); delete[] dir2; } break; } } if (!fname) { _LOGPUT("WARNING! GetPath returning NULL pointer\n"); } else _LOGPRINT(("file expected to be %s\n",fname)); } CL_Error CL_RIFFImage::Locate(char const * iname, int const enum_id) { _LOGPRINT(("RIF File image finder called for %s, id %d\n",iname,enum_id)); if (!Env_Chunk) _LOGPUT("WARNING! no .RIF file loaded\n"); if (!Env_Chunk) return CLE_RIFFERROR; switch (imode) { case CLM_ATTACHEDPALETTE: case CLM_16BIT: case CLM_24BIT: case CLM_32BIT: case CLM_GLOBALPALETTE: case CLM_TLTPALETTE: break; default: _LOGPUT("WARNING! undefined video mode\n"); return CLE_INVALIDDXMODE; } // remove projectsubdirectory from start of image name if it is there unsigned int const psdirlen = strlen(projectsubdirectory); if (!strncmp(projectsubdirectory,iname,psdirlen)) iname += psdirlen; List envdl (Env_Chunk->lookup_child("REBENVDT")); if (!envdl.size()) { _LOGPUT("WARNING! no environment data chunk\n"); return CLE_RIFFERROR; } Environment_Data_Chunk * envd = (Environment_Data_Chunk *) envdl.first_entry(); CL_Error retval = CLE_OK; Environment_Game_Mode_Chunk * egmc = 0; if (game_mode) { if (*game_mode) { List egmcl (envd->lookup_child("GAMEMODE")); for (LIF egmci(&egmcl); !egmci.done(); egmci.next()) { Environment_Game_Mode_Chunk * egmcm = (Environment_Game_Mode_Chunk *) egmci(); if (egmcm->id_equals(game_mode)) { egmc = egmcm; break; } } if (!egmc) retval = CLE_INVALIDGAMEMODE; // only returns this error if the game mode cannot be found *and* the image is not listed } } if (name) { delete[] name; name = 0; } if (iname) name = strip_file_extension(strip_path(iname)); char * rcname = 0; if (iname) { if (strchr(iname,'\\')) { rcname = new char[strlen(iname)+1]; strcpy(rcname,iname); *strchr(rcname,'\\')=0; } else if (strchr(iname,'/')) { rcname = new char[strlen(iname)+1]; strcpy(rcname,iname); *strchr(rcname,'/')=0; } } if (egmc) { int shapefoundingm = rcname ? 0 : 1; // Get the matching image 'Processor' chunk List micl = egmc->lookup_child("MATCHIMG"); Matching_Images_Chunk * mic = 0; if (micl.size()) mic = (Matching_Images_Chunk *)micl.first_entry(); List rcl = egmc->lookup_child("RIFCHILD"); for (LIF rci(&rcl); !rci.done(); rci.next()) { RIF_Child_Chunk * rcm = (RIF_Child_Chunk *) rci(); if (rcname) { if (_stricmp(rcname,rcm->rifname) && (*rcname || *rcm->filename)) continue; shapefoundingm = 1; } for (LIF bmpfi(&rcm->bmps); !bmpfi.done(); bmpfi.next()) { BMP_Flags bmpft(bmpfi()); strip_file_extension(bmpft.filename); if (iname ? !_stricmp(name,strip_path(bmpft.filename)) : enum_id == bmpft.enum_id) { // select image descriptor ImageDescriptor const idsc ( *rcm->filename ? (IDscFlags)((bmpft.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0) |IDSCF_INCLUDED) : IDSCF_0, bmpfi().filename, *rcm->filename ? rcm->rifname : 0 ); ImageDescriptor const * p_idsc = &idsc; if (mic) p_idsc = &mic->GetLoadImage(idsc); else _LOGPRINT(("WARNING! no rule to find matching images in game mode %s\n",egmc->header->mode_identifier)); // load this image GetPath(*p_idsc,envd,bmpft.flags); if (fname) { if (rcname) { delete[] rcname; rcname = 0; } flags.located = 1; return CLE_OK; } } } } List ssc = egmc->lookup_child("SHBMPNAM"); for (LIF ssi(&ssc); !ssi.done(); ssi.next()) { External_Shape_BMPs_Store_Chunk * ss = (External_Shape_BMPs_Store_Chunk *) ssi(); if (rcname) if (_stricmp(rcname,ss->shapename) && *rcname) continue; for (LIF bmpfi(&ss->bmps); !bmpfi.done(); bmpfi.next()) { BMP_Name bmpft(bmpfi()); strip_file_extension(bmpft.filename); if (iname ? !_stricmp(name,strip_path(bmpft.filename)) : enum_id == bmpft.enum_id) { // select image descriptor ImageDescriptor const idsc ( (IDscFlags)((bmpft.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0) |(ss->GetExtendedData()->flags & GBF_SPRITE ? IDSCF_SPRITE : IDSCF_SUBSHAPE) |IDSCF_INCLUDED), bmpfi().filename, ss->shapename, bmpft.flags & ChunkBMPFlag_FixedPalette ? ss->rifname : 0 ); ImageDescriptor const * p_idsc = &idsc; if (mic) p_idsc = &mic->GetLoadImage(idsc); else _LOGPRINT(("WARNING! no rule to find matching images in game mode %s\n",egmc->header->mode_identifier)); #if TRY_OLD_DIRS // temporary until all textures move to SubShps/All directory if (*p_idsc == idsc) { // select image descriptor ImageDescriptor const idsc2 ( (IDscFlags)((bmpft.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0) |(ss->GetExtendedData()->flags & GBF_SPRITE ? IDSCF_SPRITE : IDSCF_0) |IDSCF_INCLUDED), bmpfi().filename, ss->shapename, bmpft.flags & ChunkBMPFlag_FixedPalette ? ss->rifname : 0 ); ImageDescriptor const * p_idsc2 = &idsc2; if (mic) p_idsc2 = &mic->GetLoadImage(idsc2); else _LOGPRINT(("WARNING! no rule to find matching images in game mode %s\n",egmc->header->mode_identifier)); if (*p_idsc2 != idsc2) { _LOGPUT("WARNING! Not listed as in SubShps directory\n"); p_idsc = p_idsc2; } } #endif // load this image GetPath(*p_idsc,envd,bmpft.flags); if (fname) { if (rcname) { delete[] rcname; rcname = 0; } flags.located = 1; return CLE_OK; } } } } if (rcname) { if (!shapefoundingm) _LOGPRINT(("WARNING! shape/sprite %s not found in this RIF file\n",rcname)); else _LOGPRINT(("WARNING! shape/sprite %s does not appear to list %s\n",rcname,name)); } } List micl = envd->lookup_child("MATCHIMG"); Matching_Images_Chunk * mic_fix = 0; Matching_Images_Chunk * mic_nrm = 0; for (LIF mici(&micl); !mici.done(); mici.next()) { Matching_Images_Chunk * mic = (Matching_Images_Chunk *)mici(); if (mic->flags & MICF_FIXEDPALETTE) mic_fix = mic; else mic_nrm = mic; } List shapesandsprites; List shlst = Env_Chunk->lookup_child("REBSHAPE"); for (LIF shLIF(&shlst); !shLIF.done(); shLIF.next()) { List shxflst = ((Shape_Chunk *)shLIF())->lookup_child("SHPEXTFL"); if (shxflst.size()) { shapesandsprites.add_entry( (Shape_External_File_Chunk *)shxflst.first_entry() ); } } shlst = Env_Chunk->lookup_child("RSPRITES"); if (shlst.size()) { List splst = ((Chunk_With_Children *)shlst.first_entry())->lookup_child("SPRIHEAD"); for (LIF spLIF(&splst); !spLIF.done(); spLIF.next()) { shapesandsprites.add_entry( (Chunk_With_Children *)spLIF() ); } } int shapefound = rcname ? 0 : 1; for (LIF sasLIF(&shapesandsprites); !sasLIF.done(); sasLIF.next()) { char * subrifname = riff_basename(sasLIF()); if (rcname) { if (_stricmp(subrifname,rcname)) // must match shapes name exactly { delete[] subrifname; continue; } shapefound = 1; } List blsclst = sasLIF()->lookup_child("BMPLSTST"); if (blsclst.size()) { Bitmap_List_Store_Chunk * gbnc = (Bitmap_List_Store_Chunk *) blsclst.first_entry(); for (LIF bmpni(&gbnc->bmps); !bmpni.done(); bmpni.next()) { BMP_Name bmpnt(bmpni()); strip_file_extension(bmpnt.filename); if (iname ? !_stricmp(name,strip_path(bmpnt.filename)) : enum_id == bmpnt.enum_id) { // select image descriptor char * riffname = riff_basename(envd); ImageDescriptor const idsc ( (IDscFlags)((bmpnt.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0) |(gbnc->GetExtendedData()->flags & GBF_SPRITE ? IDSCF_SPRITE : IDSCF_SUBSHAPE) |IDSCF_INCLUDED), bmpni().filename, subrifname, bmpnt.flags & ChunkBMPFlag_FixedPalette ? riffname : 0 ); ImageDescriptor const * p_idsc = &idsc; delete[] riffname; if (bmpnt.flags & ChunkBMPFlag_FixedPalette) { if (mic_fix) p_idsc = &mic_fix->GetLoadImage(idsc); else _LOGPUT("WARNING! no rule to find fixed palette matching images in environment data\n"); } else { if (mic_nrm) p_idsc = &mic_nrm->GetLoadImage(idsc); else _LOGPUT("WARNING! no rule to find matching images in environment data (interface engine?)\n"); } #if TRY_OLD_DIRS // temporary until all textures move to SubShps/All directory if (*p_idsc == idsc) { // select image descriptor char * riffname = riff_basename(envd); ImageDescriptor const idsc2 ( (IDscFlags)((bmpnt.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0) |(gbnc->GetExtendedData()->flags & GBF_SPRITE ? IDSCF_SPRITE : IDSCF_0) |IDSCF_INCLUDED), bmpni().filename, subrifname, bmpnt.flags & ChunkBMPFlag_FixedPalette ? riffname : 0 ); ImageDescriptor const * p_idsc2 = &idsc2; delete[] riffname; if (bmpnt.flags & ChunkBMPFlag_FixedPalette) { if (mic_fix) p_idsc2 = &mic_fix->GetLoadImage(idsc2); else _LOGPUT("WARNING! no rule to find fixed palette matching images in environment data\n"); } else { if (mic_nrm) p_idsc2 = &mic_nrm->GetLoadImage(idsc2); else _LOGPUT("WARNING! no rule to find matching images in environment data (interface engine?)\n"); } if (*p_idsc2 != idsc2) { _LOGPUT("WARNING! Not listed as in SubShps directory\n"); p_idsc = p_idsc2; } } #endif // load this image GetPath(*p_idsc,envd,bmpnt.flags); if (fname) { delete[] subrifname; if (rcname) { delete[] rcname; rcname = 0; } flags.located = 1; return CLE_OK; } } } } delete[] subrifname; } if (rcname) { if (!shapefound) _LOGPRINT(("WARNING! shape/sprite %s not found in this RIF file\n",rcname)); else _LOGPRINT(("WARNING! shape/sprite %s does not appear to list %s\n",rcname,name)); delete[] rcname; rcname = 0; } // not found in game textures, so look in default else // but only if there is no virtual shape directory { List gbncl = envd->lookup_child("BMPNAMES"); if (gbncl.size()) { Global_BMP_Name_Chunk * gbnc = (Global_BMP_Name_Chunk *) gbncl.first_entry(); for (LIF bmpni(&gbnc->bmps); !bmpni.done(); bmpni.next()) { BMP_Name bmpnt(bmpni()); strip_file_extension(bmpnt.filename); if (iname ? !_stricmp(name,strip_path(bmpnt.filename)) : enum_id == bmpnt.enum_id) { // select image descriptor ImageDescriptor const idsc (bmpnt.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0, bmpni().filename); ImageDescriptor const * p_idsc = &idsc; if (bmpnt.flags & ChunkBMPFlag_FixedPalette) { if (mic_fix) p_idsc = &mic_fix->GetLoadImage(idsc); else _LOGPUT("WARNING! no rule to find fixed palette matching images in environment data\n"); } else { if (mic_nrm) p_idsc = &mic_nrm->GetLoadImage(idsc); else _LOGPUT("WARNING! no rule to find matching images in environment data (interface engine?)\n"); } // load this image GetPath(*p_idsc,envd,bmpnt.flags); if (fname) { flags.located = 1; return CLE_OK; } } } } } if (retval != CLE_OK) return retval; return CLE_FINDERROR; }