ff7DataInstaller.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. #include "ff7DataInstaller.h"
  2. #include <boost/filesystem.hpp>
  3. #include <boost/program_options.hpp>
  4. #include <OgreConfigFile.h>
  5. #include <OgreArchiveManager.h>
  6. #include <OgreMeshSerializer.h>
  7. #include <OgreSkeletonSerializer.h>
  8. #include <OgreMeshManager.h>
  9. #include <OgreRenderWindow.h>
  10. #include <OgreHardwarePixelBuffer.h>
  11. #include "QGearsGameState.h"
  12. #include "data/QGearsAFileManager.h"
  13. #include "data/QGearsBackgroundFileManager.h"
  14. #include "data/QGearsCameraMatrixFileManager.h"
  15. #include "data/QGearsHRCFileManager.h"
  16. #include "data/QGearsLZSFLevelFileManager.h"
  17. #include "data/QGearsPaletteFileManager.h"
  18. #include "data/QGearsPFileManager.h"
  19. #include "data/QGearsRSDFileManager.h"
  20. #include "data/QGearsTexCodec.h"
  21. #include "map/QGearsBackground2DFileManager.h"
  22. #include "map/QGearsWalkmeshFileManager.h"
  23. #include "data/FF7ModelListFileManager.h"
  24. #include "data/QGearsLGPArchiveFactory.h"
  25. #include "common/QGearsStringUtil.h"
  26. #include "common/FF7NameLookup.h"
  27. #include "data/QGearsTexCodec.h"
  28. #include "decompiler/sudm.h"
  29. FF7DataInstaller::FF7DataInstaller()
  30. #ifdef _DEBUG
  31. : mApp("plugins_d.cfg", "resources_d.cfg", "install_d.log")
  32. #else
  33. : mApp("plugins.cfg", "resources.cfg", "install.log")
  34. #endif
  35. {
  36. mApp.initOgre(true);
  37. }
  38. FF7DataInstaller::~FF7DataInstaller()
  39. {
  40. }
  41. void FF7DataInstaller::Convert(std::string inputDir, std::string outputDir, const std::vector<std::string>& files)
  42. {
  43. for (const auto& file : files)
  44. {
  45. if (file == "field/char.lgp")
  46. {
  47. /*
  48. auto fullPath = inputDir + file;
  49. mApp.getRoot()->addResourceLocation(fullPath, "LGP", "FFVII");
  50. ConvertFieldModels(fullPath, outputDir);
  51. mApp.getRoot()->removeResourceLocation(fullPath, "FFVII");*/
  52. }
  53. else if (file == "field/flevel.lgp")
  54. {
  55. auto fullPath = inputDir + file;
  56. mApp.getRoot()->addResourceLocation(fullPath, "LGP", "FFVIIFields");
  57. ConvertFields(fullPath, outputDir);
  58. mApp.getRoot()->removeResourceLocation(fullPath, "FFVIIFields");
  59. }
  60. }
  61. }
  62. // TOOD: Share with pc model exporter
  63. static void exportMesh(std::string outdir, const Ogre::MeshPtr &mesh)
  64. {
  65. Ogre::MeshSerializer mesh_ser;
  66. mesh_ser.exportMesh(mesh.getPointer(), outdir + mesh->getName());
  67. Ogre::SkeletonPtr skeleton(mesh->getSkeleton());
  68. Ogre::SkeletonSerializer sk_ser;
  69. sk_ser.exportSkeleton(skeleton.getPointer(), outdir + skeleton->getName());
  70. Ogre::Mesh::SubMeshIterator it(mesh->getSubMeshIterator());
  71. Ogre::MaterialSerializer mat_ser;
  72. size_t i(0);
  73. while (it.hasMoreElements())
  74. {
  75. Ogre::SubMesh *sub_mesh(it.getNext());
  76. Ogre::MaterialPtr mat(Ogre::MaterialManager::getSingleton().getByName(sub_mesh->getMaterialName()));
  77. if (!mat.isNull())
  78. {
  79. mat_ser.queueForExport(mat);
  80. }
  81. ++i;
  82. }
  83. QGears::String base_name;
  84. QGears::StringUtil::splitFull(mesh->getName(), base_name);
  85. mat_ser.exportQueued(outdir + base_name + QGears::EXT_MATERIAL);
  86. }
  87. void FF7DataInstaller::ConvertFieldModels(std::string archive, std::string outDir)
  88. {
  89. Ogre::StringVectorPtr resources = mApp.ResMgr()->listResourceNames("FFVII", "*.hrc");
  90. for (auto& resourceName : *resources)
  91. {
  92. if (QGears::StringUtil::endsWith(resourceName, ".hrc"))
  93. {
  94. //try
  95. {
  96. Ogre::ResourcePtr hrc = QGears::HRCFileManager::getSingleton().load(resourceName, "FFVII");
  97. Ogre::String baseName;
  98. QGears::StringUtil::splitBase(resourceName, baseName);
  99. auto meshName = QGears::FF7::NameLookup::model(baseName) + ".mesh";
  100. Ogre::MeshPtr mesh(Ogre::MeshManager::getSingleton().load(meshName, "FFVII"));
  101. Ogre::SkeletonPtr skeleton(mesh->getSkeleton());
  102. exportMesh(outDir, mesh);
  103. }
  104. // catch (const Ogre::Exception& ex)
  105. {
  106. // std::cout << "ERROR converting: " << resourceName << " Exception: " << ex.what() << std::endl;
  107. }
  108. }
  109. }
  110. /*
  111. TODO:
  112. To figure out what .a files relate to which .hrc files, we need to enumerate every field
  113. and check its model loader data. These are always Idle, Walk, Run and then field specific
  114. ordering.
  115. Model loader is section 3 of the field file.
  116. */
  117. }
  118. class FF7FieldScriptFormatter : public SUDM::IScriptFormatter
  119. {
  120. public:
  121. virtual bool ExcludeFunction(const std::string& ) override
  122. {
  123. // Include everything for now
  124. return false;
  125. }
  126. virtual std::string RenameIdentifer(const std::string& name) override
  127. {
  128. // Don't rename anything for now
  129. return name;
  130. }
  131. };
  132. static void FF7PcFieldToQGearsField(QGears::FLevelFilePtr& field, const std::string& outDir)
  133. {
  134. // Save out the tiles as a PNG image
  135. try
  136. {
  137. // Get the raw script bytes
  138. const std::vector<u8> rawFieldData = field->getRawScript();
  139. // Decompile to LUA
  140. FF7FieldScriptFormatter formatter;
  141. std::string luaScript = SUDM::FF7::Field::Decompile(field->getName(), rawFieldData, formatter);
  142. std::cout << luaScript << std::endl;
  143. }
  144. catch (const ::InternalDecompilerError& ex)
  145. {
  146. std::cerr << "InternalDecompilerError: " << ex.what() << std::endl;
  147. }
  148. //const QGears::ModelListFilePtr& models = field->getModelList();
  149. //const QGears::ModelListFile::ModelDescription& desc = models->getModels().at(0);
  150. const QGears::PaletteFilePtr& pal = field->getPalette();
  151. const QGears::BackgroundFilePtr& bg = field->getBackground();
  152. std::unique_ptr<Ogre::Image> bgImage(bg->createImage(pal));
  153. bgImage->save(outDir + "/" + field->getName() + ".png");
  154. {
  155. TiXmlDocument doc;
  156. std::unique_ptr<TiXmlElement> element(new TiXmlElement("background2d"));
  157. // Magic constants
  158. const int kScaleUpFactor = 3;
  159. const int kPsxScreenWidth = 320;
  160. const int kPsxScreenHeight = 240;
  161. // Get texture atlas size
  162. const int width = bgImage->getWidth();
  163. const int height = bgImage->getHeight();
  164. const QGears::CameraMatrixFilePtr& camMatrix = field->getCameraMatrix();
  165. const Ogre::Vector3 position = camMatrix->getPosition();
  166. const Ogre::Quaternion orientation = camMatrix->getOrientation();
  167. const Ogre::Degree fov = camMatrix->getFov(static_cast<float>(kPsxScreenHeight));
  168. const QGears::TriggersFilePtr& triggers = field->getTriggers();
  169. const int min_x = triggers->getCameraRange().left * kScaleUpFactor;
  170. const int min_y = triggers->getCameraRange().top * kScaleUpFactor;
  171. const int max_x = triggers->getCameraRange().right * kScaleUpFactor;
  172. const int max_y = triggers->getCameraRange().bottom * kScaleUpFactor;
  173. element->SetAttribute("image", field->getName() + ".png");
  174. element->SetAttribute("position", Ogre::StringConverter::toString(position));
  175. element->SetAttribute("orientation", Ogre::StringConverter::toString(orientation));
  176. element->SetAttribute("fov", Ogre::StringConverter::toString(fov));
  177. element->SetAttribute("range", std::to_string(min_x) + " " + std::to_string(min_y) + " " + std::to_string(max_x) + " " + std::to_string(max_y));
  178. element->SetAttribute("clip", std::to_string(kPsxScreenWidth * kScaleUpFactor) + " " + std::to_string(kPsxScreenHeight * kScaleUpFactor));
  179. // Write out the *_BG.XML data
  180. auto& layers = bg->getLayers();
  181. for (const auto& layer : layers)
  182. {
  183. // TODO: Should we only output tiles to construct enabled layers?
  184. // if (layer.enabled)
  185. {
  186. for (const QGears::BackgroundFile::SpriteData& sprite : layer.sprites)
  187. {
  188. std::unique_ptr<TiXmlElement> xmlElement(new TiXmlElement("tile"));
  189. xmlElement->SetAttribute("destination",
  190. Ogre::StringConverter::toString(sprite.dst.x * kScaleUpFactor) + " " +
  191. Ogre::StringConverter::toString(sprite.dst.y * kScaleUpFactor));
  192. xmlElement->SetAttribute("width", Ogre::StringConverter::toString(sprite.width * kScaleUpFactor));
  193. xmlElement->SetAttribute("height", Ogre::StringConverter::toString(sprite.height * kScaleUpFactor));
  194. // Each tile is added to a big texture atlas with hard coded size of 1024x1024, convert UV's to the 0.0f to 1.0f range
  195. const float u0 = static_cast<float>(sprite.src.x) / bgImage->getWidth();
  196. const float v0 = static_cast<float>(sprite.src.y) / bgImage->getHeight();
  197. const float u1 = static_cast<float>(sprite.src.x + sprite.width) / bgImage->getWidth();
  198. const float v1 = static_cast<float>(sprite.src.y + sprite.height) / bgImage->getHeight();
  199. xmlElement->SetAttribute("uv",
  200. Ogre::StringConverter::toString(u0) + " " + Ogre::StringConverter::toString(v0) + " " +
  201. Ogre::StringConverter::toString(u1) + " " + Ogre::StringConverter::toString(v1)
  202. );
  203. // TODO: Figure out how to scale this value correctly
  204. xmlElement->SetAttribute("depth", "999" /* Ogre::StringConverter::toString(static_cast<float>(sprite.depth) / (4096.0f/10.0f))*/);
  205. // TODO: Copied from DatFile::AddTile - add to common method
  206. Ogre::String blending_str = "";
  207. if (sprite.blending == 0)
  208. {
  209. blending_str = "alpha";
  210. }
  211. else if (sprite.blending == 1)
  212. {
  213. blending_str = "add";
  214. }
  215. else if (sprite.blending == 2)
  216. {
  217. blending_str = "subtract";
  218. }
  219. else
  220. {
  221. blending_str = "unknown";
  222. }
  223. xmlElement->SetAttribute("blending", blending_str);
  224. element->LinkEndChild(xmlElement.release());
  225. }
  226. }
  227. }
  228. doc.LinkEndChild(element.release());
  229. doc.SaveFile(outDir + "/" + field->getName() + "_bg.xml");
  230. }
  231. {
  232. // Save out the walk mesh as XML
  233. const QGears::WalkmeshFilePtr& walkmesh = field->getWalkmesh();
  234. TiXmlDocument doc;
  235. std::unique_ptr<TiXmlElement> element(new TiXmlElement("walkmesh"));
  236. for (QGears::WalkmeshFile::Triangle& tri : walkmesh->getTriangles())
  237. {
  238. std::unique_ptr<TiXmlElement> xmlElement(new TiXmlElement("triangle"));
  239. xmlElement->SetAttribute("a", Ogre::StringConverter::toString(tri.a));
  240. xmlElement->SetAttribute("b", Ogre::StringConverter::toString(tri.b));
  241. xmlElement->SetAttribute("c", Ogre::StringConverter::toString(tri.c));
  242. xmlElement->SetAttribute("a_b", std::to_string(tri.access_side[0]));
  243. xmlElement->SetAttribute("b_c", std::to_string(tri.access_side[1]));
  244. xmlElement->SetAttribute("c_a", std::to_string(tri.access_side[2]));
  245. element->LinkEndChild(xmlElement.release());
  246. }
  247. doc.LinkEndChild(element.release());
  248. doc.SaveFile(outDir + "/" + field->getName() + "_wm.xml");
  249. }
  250. }
  251. void FF7DataInstaller::ConvertFields(std::string archive, std::string outDir)
  252. {
  253. // Everything in here is a field
  254. Ogre::StringVectorPtr resources = mApp.ResMgr()->listResourceNames("FFVIIFields", "*");
  255. for (auto& resourceName : *resources)
  256. {
  257. if (!QGears::StringUtil::endsWith(resourceName, ".tex")
  258. && !QGears::StringUtil::endsWith(resourceName, ".tut")
  259. && !QGears::StringUtil::endsWith(resourceName, ".siz")
  260. && resourceName != "maplist" && resourceName == "md1_2")
  261. {
  262. //try
  263. {
  264. QGears::FLevelFilePtr field = QGears::LZSFLevelFileManager::getSingleton().load(resourceName, "FFVIIFields").staticCast<QGears::FLevelFile>();
  265. FF7PcFieldToQGearsField(field, outDir);
  266. }
  267. /*
  268. catch (const Ogre::Exception& ex)
  269. {
  270. std::cout << "ERROR converting: " << resourceName << " Exception: " << ex.what() << std::endl;
  271. }
  272. catch (const std::exception& ex)
  273. {
  274. std::cout << "ERROR converting: " << resourceName << " Exception: " << ex.what() << std::endl;
  275. }*/
  276. }
  277. }
  278. }