diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index a9e4306..b7c0663 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -134,6 +134,7 @@ set(src_redalert ./RedAlert/BASE64.CPP ./RedAlert/BASE64.H ./RedAlert/BBDATA.CPP + ./RedAlert/BDATAXML.CPP ./RedAlert/BDATA.CPP ./RedAlert/BENCH.CPP ./RedAlert/BENCH.H diff --git a/code/REDALERT/BDATA.CPP b/code/REDALERT/BDATA.CPP index 5fe0762..7727f78 100644 --- a/code/REDALERT/BDATA.CPP +++ b/code/REDALERT/BDATA.CPP @@ -3141,12 +3141,9 @@ void BuildingTypeClass::One_Time(void) _makepath(fullname, NULL, NULL, building.Graphic_Name(), ".SHP"); ((void const *&)building.ImageData) = MFCD::Retrieve(fullname); { - char imageFileName[512]; - sprintf(imageFileName, "DATA/ART/TEXTURES/SRGB/RED_ALERT/STRUCTURES/%s/%s-0000.TGA", building.Graphic_Name(), building.Graphic_Name()); - ((void const*&)building.HDImageData) = Image_LoadImage(imageFileName, true, true); + const char* imageFileName = Buildings_FindHDTexture(fullname, 0, 0); - if (!building.HDImageData) { - sprintf(imageFileName, "DATA/ART/TEXTURES/SRGB/RED_ALERT/STRUCTURES/%s/%s-0000-0000.TGA", building.Graphic_Name(), building.Graphic_Name()); + if (imageFileName) { ((void const*&)building.HDImageData) = Image_LoadImage(imageFileName, true, true); } @@ -3393,15 +3390,11 @@ void BuildingTypeClass::Init(TheaterType theater) ((void const *&)classptr->ImageData) = MFCD::Retrieve(fullname); // jmarshall { - char imageFileName[512]; + const char* imageFileName = Buildings_FindHDTexture(fullname, 0, 0); - // Try load the theatre specific asset first - sprintf(imageFileName, "DATA/ART/TEXTURES/SRGB/RED_ALERT/TERRAIN/%s/%s.%s/%s.%s-0000.DDS", Theaters[theater].Name, classptr->Graphic_Name(), Theaters[theater].Suffix, classptr->Graphic_Name(), Theaters[theater].Suffix); - ((BuildingTypeClass*)classptr)->HDImageData = Image_LoadImage(imageFileName); - - if (!((BuildingTypeClass*)classptr)->HDImageData) { - sprintf(imageFileName, "DATA/ART/TEXTURES/SRGB/RED_ALERT/STRUCTURES/%s/%s-0000.TGA", classptr->Graphic_Name(), classptr->Graphic_Name()); - ((BuildingTypeClass*)classptr)->HDImageData = Image_LoadImage(imageFileName); + // Try load the theatre specific asset first + if (imageFileName) { + ((BuildingTypeClass*)classptr)->HDImageData = Image_LoadImage(imageFileName, true, true); } if (classptr->ImageData != NULL && classptr->HDImageData != NULL) { diff --git a/code/REDALERT/BDATAXML.CPP b/code/REDALERT/BDATAXML.CPP new file mode 100644 index 0000000..a048aad --- /dev/null +++ b/code/REDALERT/BDATAXML.CPP @@ -0,0 +1,92 @@ +// BDATAXML.CPP +// + +#include "FUNCTION.H" +#include "tinyxml2.h" + +#include +#include + +int64_t generateHashValue(const char* fname, const int size); + +struct BuildingsTileRule_t { + std::string name; + int64_t hash; + int shape; + std::vector frames; +}; + +struct BuildingsXMLInfo_t { + std::vector tiles; +}; + +BuildingsXMLInfo_t buildingsXmlRules; + +const char* Buildings_FindHDTexture(const char* shapeFileName, int shapeNum, int frameNum) { + char tmpFileName[2048]; + strcpy(tmpFileName, shapeFileName); + COM_SetExtension(tmpFileName, strlen(tmpFileName), ""); + int64_t hash = generateHashValue(tmpFileName, strlen(tmpFileName)); + for (int i = 0; i < buildingsXmlRules.tiles.size(); i++) { + if (buildingsXmlRules.tiles[i].hash == hash && buildingsXmlRules.tiles[i].shape == shapeNum) { + static char hdTexturePath[2048]; + sprintf(hdTexturePath, "DATA/ART/TEXTURES/SRGB/RED_ALERT/STRUCTURES/%s", buildingsXmlRules.tiles[i].frames[frameNum].c_str()); + return &hdTexturePath[0]; + } + } + return NULL; +} + +int Buildings_GetNumFramesForTile(const char* shapeFileName, int shapeNum) { + int64_t hash = generateHashValue(shapeFileName, strlen(shapeFileName)); + for (int i = 0; i < buildingsXmlRules.tiles.size(); i++) { + if (buildingsXmlRules.tiles[i].hash == hash && buildingsXmlRules.tiles[i].shape == shapeNum) { + return buildingsXmlRules.tiles[i].frames.size(); + } + } + return 0; +} + +void Buildings_ParseTile(tinyxml2::XMLNode* tile, BuildingsTileRule_t& tileRule) { + tinyxml2::XMLNode* KeyNode = tile->FirstChildElement("Key"); + tinyxml2::XMLNode* NameNode = KeyNode->FirstChildElement("Name"); + tinyxml2::XMLNode* ShapeNode = KeyNode->FirstChildElement("Shape"); + tinyxml2::XMLNode* ValueNode = tile->FirstChildElement("Value"); + tinyxml2::XMLNode* FramesNode = ValueNode->FirstChildElement("Frames"); + tinyxml2::XMLNode* FrameNode = FramesNode->FirstChildElement("Frame"); + + tileRule.name = NameNode->FirstChild()->ToText()->Value(); + tileRule.hash = generateHashValue(tileRule.name.c_str(), tileRule.name.size()); + tileRule.shape = atoi(ShapeNode->FirstChild()->ToText()->Value()); + + while (FrameNode != NULL) { + if (FrameNode->FirstChild() != NULL) { + tileRule.frames.push_back(FrameNode->FirstChild()->ToText()->Value()); + } + FrameNode = FrameNode->NextSiblingElement("Frame"); + } +} + +void Buildings_LoadRuleXML(const char* path, BuildingsXMLInfo_t& info) { + tinyxml2::XMLDocument doc; + doc.LoadFile(path); + + tinyxml2::XMLElement* root = doc.FirstChildElement(); + if (root == NULL) + return; + + tinyxml2::XMLNode* tilesetTypeClassNode = root->FirstChild(); + + tinyxml2::XMLNode* tilesParent = tilesetTypeClassNode->FirstChildElement("Tiles"); + tinyxml2::XMLNode* tile = tilesParent->FirstChildElement("Tile"); + while (tile != NULL) { + BuildingsTileRule_t tileRule; + Buildings_ParseTile(tile, tileRule); + info.tiles.push_back(tileRule); + tile = tile->NextSiblingElement("Tile"); + } +} + +void Buildings_LoadRules(void) { + Buildings_LoadRuleXML("data/xml/tilesets/RA_STRUCTURES.XML", buildingsXmlRules); +} \ No newline at end of file diff --git a/code/REDALERT/FUNCTION.H b/code/REDALERT/FUNCTION.H index d90273e..adb300a 100644 --- a/code/REDALERT/FUNCTION.H +++ b/code/REDALERT/FUNCTION.H @@ -1180,8 +1180,12 @@ __forceinline void COM_SetExtension(char* path, int maxSize, const char* extensi } void Tileset_LoadRules(void); +void Buildings_LoadRules(void); + const char* Tileset_FindHDTexture(int theaterType, const char* shapeFileName, int shapeNum, int frameNum); int Tileset_GetNumFramesForTile(int theaterType, const char* shapeFileName, int shapeNum); +int Buildings_GetNumFramesForTile(const char* shapeFileName, int shapeNum); +const char* Buildings_FindHDTexture(const char* shapeFileName, int shapeNum, int frameNum); extern bool g_inMainMenu; extern KeyNumType g_globalKeyNumType; diff --git a/code/REDALERT/STARTUP.CPP b/code/REDALERT/STARTUP.CPP index 8721184..5f98dd5 100644 --- a/code/REDALERT/STARTUP.CPP +++ b/code/REDALERT/STARTUP.CPP @@ -389,6 +389,7 @@ int PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int // Load all of the XML files. Tileset_LoadRules(); + Buildings_LoadRules(); if (Parse_Command_Line(argc, argv)) { diff --git a/code/REDALERT/WINSTUB.CPP b/code/REDALERT/WINSTUB.CPP index a105a1d..4ddea6b 100644 --- a/code/REDALERT/WINSTUB.CPP +++ b/code/REDALERT/WINSTUB.CPP @@ -160,7 +160,7 @@ void Image_WriteTGA(const char* filename, const byte* data, int width, int heigh static char* Image_GetGeneratedName(Image_t* image, const char* name, int houseid, int animid, int64_t hash) { static char generatedFileName[1024]; - sprintf(generatedFileName, "cache/%d.%d.%d.tga", hash, houseid, animid); + sprintf(generatedFileName, "cache/v2.%d.%d.%d.tga", hash, houseid, animid); return &generatedFileName[0]; } @@ -183,9 +183,12 @@ static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int } bool swapBGR = false; - if (strstr(name, ".TGA")) { - iluFlipImage(); - swapBGR = true; + if (strstr(name, ".TGA") || strstr(name, ".tga")) { + if (!writeGenerated) + { + iluFlipImage(); + swapBGR = true; + } } ILuint Width, Height, Bpp;