divapvmod.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using DivaScript;
  8. using ft_universal_parser;
  9. using MikuMikuModel.FarcPack;
  10. using ScriptUtilities;
  11. using MikuMikuLibrary;
  12. using MikuMikuLibrary.Sprites;
  13. using MikuMikuLibrary.Textures;
  14. using MikuMikuLibrary.Databases;
  15. using System.Drawing;
  16. using MikuMikuLibrary.Archives.Farc;
  17. namespace ft_module_parser
  18. {
  19. class divapvmod
  20. {
  21. pv_dbs_raw pv_orig = new pv_dbs_raw();
  22. pv_fields pv_field = new pv_fields();
  23. pv_lists_raw pv_list = new pv_lists_raw();
  24. SpriteDatabase spritedb = new SpriteDatabase();
  25. public void RestoreDb(bool skipuserinput = false, bool isConsole = false)
  26. {
  27. if (File.Exists(@"rom\pv_db.bak"))
  28. {
  29. File.Copy("rom\\pv_db.bak", "rom\\pv_db.txt", true);
  30. File.Delete(@"rom\pv_db.bak");
  31. }
  32. if (File.Exists(@"rom\pv_field.bak"))
  33. {
  34. File.Copy("rom\\pv_field.bak", "rom\\pv_field.txt", true);
  35. File.Delete(@"rom\pv_field.bak");
  36. }
  37. if (!isConsole)
  38. {
  39. if (File.Exists(@"rom\gm_pv_list_tbl.bak"))
  40. {
  41. File.Copy("rom\\gm_pv_list_tbl.bak", "rom\\gm_pv_list_tbl.farc", true);
  42. File.Delete(@"rom\gm_pv_list_tbl.bak");
  43. }
  44. }
  45. Console.WriteLine("DB Restored!");
  46. if (!skipuserinput) Console.ReadKey();
  47. }
  48. //gametype 0 = ac
  49. //gametype 1 = aft
  50. public void ApplyMods(int gametype = 0, string gamepath = "", bool forcemod = false, bool isConsole = false)
  51. {
  52. pv_list.game_type = gametype;
  53. if (gamepath.Count() != 0)
  54. gamepath = gamepath + "\\";
  55. if (!File.Exists(gamepath + @"rom\pv_db.bak"))
  56. {
  57. if (!forcemod)
  58. {
  59. Console.WriteLine("Welcome to lyb's DivaAutoMod tool v3");
  60. if (gametype == 0)
  61. {
  62. Console.WriteLine("Before we get started, this tool currently does not support cleaning the files back.");
  63. Console.WriteLine("So it is recommended to use a make another copy of the game or delete the modded files manually.");
  64. Console.WriteLine("However, you can restore the DB so the modded pv won't show up by running this software with \"-restore\" parameter");
  65. Console.WriteLine("If you agree with this behaviour, type \"AGREE\" in full caps.");
  66. Console.WriteLine("This message will no longer show up once you Agree.");
  67. }
  68. if (gametype == 1)
  69. {
  70. Console.WriteLine("Before we get started, this tool will modify `mdata\\M999` folder. ");
  71. Console.WriteLine("Make sure there are no other mods using it.");
  72. Console.WriteLine("If you agree with this behaviour, type \"AGREE\" in full caps.");
  73. Console.WriteLine("This message will no longer show up once you Agree.");
  74. }
  75. Console.Write("Input=");
  76. var inp = Console.ReadLine();
  77. if (inp != "AGREE")
  78. {
  79. Environment.Exit(0);
  80. }
  81. }
  82. File.Copy(gamepath + "rom\\pv_db.txt", gamepath + "rom\\pv_db.bak");
  83. }
  84. if (gametype == 1)
  85. {
  86. if (!Directory.Exists(gamepath + "mdata\\M999"))
  87. Directory.CreateDirectory(gamepath + "mdata\\M999");
  88. if (!Directory.Exists(gamepath + "mdata\\M999\\rom"))
  89. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom");
  90. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\auth_3d"))
  91. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\auth_3d");
  92. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\rob"))
  93. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\rob");
  94. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\script"))
  95. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\script");
  96. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\objset"))
  97. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\objset");
  98. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\movie"))
  99. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\movie");
  100. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\sound"))
  101. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\sound");
  102. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\2d"))
  103. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\2d");
  104. if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\sound\\song"))
  105. Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\sound\\song");
  106. //Logs.WriteLine("### MDATA LOAD ###");
  107. mdataUtilities.getMdatas(gamepath + @"mdata\");
  108. for (int i = 0; i < 7; i++)
  109. {
  110. mdataUtilities.getPath(gamepath + @"mdata\", (mdataUtilities.dbType)i);
  111. }
  112. //Logs.WriteLine(mdataUtilities.getPath(acpath + @"\mdata", (mdataUtilities.dbType)i));
  113. //Logs.WriteLine("### MDATA DONE ###");
  114. }
  115. if (!File.Exists(gamepath + @"rom\pv_field.bak"))
  116. File.Copy(gamepath + "rom\\pv_field.txt", gamepath + "rom\\pv_field.bak");
  117. if (!isConsole)
  118. if (!File.Exists(gamepath + @"rom\gm_pv_list_tbl.bak"))
  119. File.Copy(gamepath + "rom\\gm_pv_list_tbl.farc", gamepath + "rom\\gm_pv_list_tbl.bak");
  120. pv_orig.load(gamepath + @"rom\pv_db.bak");
  121. if (gametype == 1)
  122. pv_orig.loadmdata(mdataUtilities.getPath(gamepath + "mdata", mdataUtilities.dbType.pv_db));
  123. pv_field.load(gamepath + @"rom\pv_field.bak");
  124. if (!isConsole)
  125. Tools.Extract(gamepath + @"rom\gm_pv_list_tbl.bak");
  126. if (!isConsole)
  127. pv_list.load(gamepath + @"rom\gm_pv_list_tbl\gm_pv_list.bin");
  128. if (gametype == 1)
  129. spritedb.Load(mdataUtilities.getPath(gamepath + "mdata", mdataUtilities.dbType.spr_db));
  130. foreach (string file in Directory.EnumerateFiles(gamepath + "divamods\\", "mod.txt", SearchOption.AllDirectories))
  131. {
  132. string name = "";
  133. string author = "";
  134. int ver = 0;
  135. int pvid = -1;
  136. string type = "";
  137. string base_name = "";
  138. var path = Path.GetDirectoryName(file);
  139. using (StreamReader modtxt = new StreamReader(file))
  140. {
  141. while (modtxt.Peek() >= 0)
  142. {
  143. var line = modtxt.ReadLine();
  144. if (!line.StartsWith("#"))
  145. {
  146. int index = line.IndexOf('=');
  147. string first = line.Substring(0, index);
  148. string second = line.Substring(index + 1);
  149. if (first == "name")
  150. name = second;
  151. if (first == "author")
  152. author = second;
  153. if (first == "ver")
  154. ver = int.Parse(second);
  155. if (first == "pvid")
  156. pvid = int.Parse(second);
  157. if (first == "type")
  158. type = second;
  159. if (first == "base_name")
  160. base_name = second;
  161. }
  162. }
  163. }
  164. //apply dbs (pv_db, gm_pv_list, pv_field)
  165. Console.WriteLine("Found Mod " + name + " by " + author);
  166. bool modloaded = false;
  167. if (ver == 1)
  168. {
  169. modloaded = true;
  170. int id = pv_orig.merge(path + "\\pv_db.txt", pv_list);
  171. Console.WriteLine("Created new PV ID at " + id);
  172. if (File.Exists(path + "\\pv_field.txt"))
  173. pv_field.merge(path + "\\pv_field.txt", id);
  174. if (gametype == 1)
  175. {
  176. //copy other stuff
  177. if (Directory.Exists(path + "\\movie"))
  178. Tools.CopyFiles(path + "\\movie\\", gamepath + @"mdata\m999\rom\movie\");
  179. if (Directory.Exists(path + "\\script"))
  180. Tools.CopyFiles(path + "\\script\\", gamepath + @"mdata\m999\rom\script\");
  181. if (Directory.Exists(path + "\\song"))
  182. Tools.CopyFiles(path + "\\song\\", gamepath + @"mdata\m999\rom\sound\song\");
  183. }
  184. else
  185. {
  186. //copy other stuff
  187. if (Directory.Exists(path + "\\movie"))
  188. Tools.CopyFiles(path + "\\movie\\", gamepath + @"rom\movie\");
  189. if (Directory.Exists(path + "\\script"))
  190. Tools.CopyFiles(path + "\\script\\", gamepath + @"rom\script\");
  191. if (Directory.Exists(path + "\\song"))
  192. Tools.CopyFiles(path + "\\song\\", gamepath + @"rom\sound\song\");
  193. }
  194. }
  195. if ((ver == 2) || (ver == 3))
  196. {
  197. modloaded = true;
  198. if (type == "edit_2nd")
  199. {
  200. try
  201. {
  202. ValueTuple<List<PvCommand>, PvDatabaseInfo> ftEditCommands = Diva2ndEditScript.GetFtEditCommands(new EditMode.Diva2nd.Edit(path + "//SECURE.bin"), 000);
  203. List<PvCommand> pvCommandList = ftEditCommands.Item1;
  204. PvDatabaseInfo pvDatabaseInfo = ftEditCommands.Item2;
  205. if (pvCommandList == null || pvDatabaseInfo == null)
  206. return;
  207. var pv_cmd = pvCommandList;
  208. var pv_db = (IEnumerable<string>)pvDatabaseInfo.GetDiva2ndPvDbAc(base_name);
  209. if (gametype == 1)
  210. pv_db = (IEnumerable<string>)pvDatabaseInfo.GetDiva2ndPvDb(base_name);
  211. var pv_field = (IEnumerable<string>)pvDatabaseInfo.GetDiva2ndFieldDb();
  212. if (!Directory.Exists(path + "\\script"))
  213. Directory.CreateDirectory(path + "\\script");
  214. using (StreamWriter outp = new StreamWriter(path + "\\pv_db.txt"))
  215. {
  216. foreach (var i in pv_db)
  217. outp.WriteLine(i);
  218. outp.Close();
  219. }
  220. using (StreamWriter outp = new StreamWriter(path + "\\pv_field.txt"))
  221. {
  222. foreach (var i in pv_field)
  223. outp.WriteLine(i);
  224. outp.Close();
  225. }
  226. PvScript.WriteBinaryScript(path + "//script//" + base_name + ".dsc", pv_cmd, Format.FT, false);
  227. }
  228. catch (Exception ex)
  229. {
  230. Console.WriteLine("--- :PokeKms: ---");
  231. Console.WriteLine(ex.ToString());
  232. modloaded = false;
  233. }
  234. }
  235. if (type == "edit_f2nd")
  236. {
  237. }
  238. if (modloaded)
  239. {
  240. int id = pv_orig.merge(path + "\\pv_db.txt", pv_list, pvid);
  241. Console.WriteLine("Created new PV ID at " + id);
  242. if (File.Exists(path + "\\pv_field.txt"))
  243. pv_field.merge(path + "\\pv_field.txt", id);
  244. if (File.Exists(path + "\\thumb\\MERGE_D5COMP_0.png"))
  245. if (File.Exists(path + "\\thumb\\MERGE_D5COMP_1.png"))
  246. {
  247. SpriteSet sprite = new SpriteSet();
  248. sprite.Load(new MemoryStream(rescb.spr_sel_pv));
  249. Bitmap bm0 = new Bitmap(path + "\\thumb\\MERGE_D5COMP_0.png");
  250. Bitmap bm1 = new Bitmap(path + "\\thumb\\MERGE_D5COMP_1.png");
  251. sprite.TextureSet.Textures[0] = TextureEncoder.Encode(bm0, TextureFormat.DXT5, false);
  252. sprite.TextureSet.Textures[0].Name = "MERGE_D5COMP_0";
  253. sprite.TextureSet.Textures[1] = TextureEncoder.Encode(bm1, TextureFormat.DXT5, false);
  254. sprite.TextureSet.Textures[1].Name = "MERGE_D5COMP_1";
  255. MemoryStream dest0 = new MemoryStream();
  256. sprite.Save(dest0, true);
  257. var farc = new FarcArchive();
  258. farc.Add("spr_sel_pv" + String.Format("{0:000}", id) + ".bin", dest0, false);
  259. farc.IsCompressed = true;
  260. farc.Save(gamepath + @"mdata\m999\rom\2d\" + "spr_sel_pv" + String.Format("{0:000}", id) + ".farc");
  261. var maxid = spritedb.SpriteSets.Max(c => c.Id);
  262. int maxsprite = 0;
  263. int maxtex = 0;
  264. foreach (var sprites in spritedb.SpriteSets)
  265. {
  266. foreach (var sprite0 in sprites.Sprites)
  267. if (maxid < sprite0.Id) maxid = sprite0.Id;
  268. foreach (var tex0 in sprites.Textures)
  269. if (maxid < tex0.Id) maxid = tex0.Id;
  270. }
  271. maxid++;
  272. var newsprite = new SpriteSetEntry();
  273. newsprite.Name = "SPR_SEL_PV" + String.Format("{0:000}", id);
  274. newsprite.FileName = "spr_sel_pv" + String.Format("{0:000}", id) + ".bin";
  275. newsprite.Id = maxid;
  276. maxid++;
  277. var sprentry0 = new SpriteEntry();
  278. sprentry0.Id = maxid;
  279. sprentry0.Index = 0;
  280. sprentry0.Name = "SPR_SEL_PV" + String.Format("{0:000}", id) + "_SONG_BG" + String.Format("{0:000}", id);
  281. maxid++;
  282. var sprentry1 = new SpriteEntry();
  283. sprentry1.Id = maxid;
  284. sprentry1.Index = 1;
  285. sprentry1.Name = "SPR_SEL_PV" + String.Format("{0:000}", id) + "_SONG_JK" + String.Format("{0:000}", id);
  286. maxid++;
  287. var sprentry2 = new SpriteEntry();
  288. sprentry2.Id = maxid;
  289. sprentry2.Index = 2;
  290. sprentry2.Name = "SPR_SEL_PV" + String.Format("{0:000}", id) + "_SONG_LOGO" + String.Format("{0:000}", id);
  291. maxid++;
  292. var texentry0 = new SpriteTextureEntry();
  293. texentry0.Id = maxid;
  294. texentry0.Index = 0;
  295. texentry0.Name = "SPRTEX_SEL_PV" + String.Format("{0:000}", id) + "_MERGE_BC5COMP_0";
  296. maxid++;
  297. var texentry1 = new SpriteTextureEntry();
  298. texentry1.Id = maxid;
  299. texentry1.Index = 1;
  300. texentry1.Name = "SPRTEX_SEL_PV" + String.Format("{0:000}", id) + "_MERGE_D5COMP_0";
  301. newsprite.Sprites.Add(sprentry0);
  302. newsprite.Sprites.Add(sprentry1);
  303. newsprite.Sprites.Add(sprentry2);
  304. newsprite.Textures.Add(texentry0);
  305. newsprite.Textures.Add(texentry1);
  306. spritedb.SpriteSets.Add(newsprite);
  307. }
  308. if (gametype == 1)
  309. {
  310. //copy other stuff
  311. if (Directory.Exists(path + "\\movie"))
  312. Tools.CopyFiles(path + "\\movie\\", gamepath + @"mdata\m999\rom\movie\");
  313. if (Directory.Exists(path + "\\script"))
  314. Tools.CopyFiles(path + "\\script\\", gamepath + @"mdata\m999\rom\script\", true);
  315. if (Directory.Exists(path + "\\song"))
  316. Tools.CopyFiles(path + "\\song\\", gamepath + @"mdata\m999\rom\sound\song\");
  317. }
  318. else
  319. {
  320. //copy other stuff
  321. if (Directory.Exists(path + "\\movie"))
  322. Tools.CopyFiles(path + "\\movie\\", gamepath + @"rom\movie\");
  323. if (Directory.Exists(path + "\\script"))
  324. Tools.CopyFiles(path + "\\script\\", gamepath + @"rom\script\", true);
  325. if (Directory.Exists(path + "\\song"))
  326. Tools.CopyFiles(path + "\\song\\", gamepath + @"rom\sound\song\");
  327. }
  328. }
  329. }
  330. if (!modloaded) Console.WriteLine("Skipped. This mod probably requires a newer version of lybDivaMods.");
  331. }
  332. if (gametype == 1)
  333. {
  334. if (!Directory.Exists(gamepath + @"mdata\m999\rom\gm_pv_list_tbl"))
  335. Directory.CreateDirectory(gamepath + @"mdata\m999\rom\gm_pv_list_tbl");
  336. if (!isConsole)
  337. {
  338. pv_list.SaveTo(gamepath + @"mdata\m999\rom\gm_pv_list_tbl\gm_pv_list.bin");
  339. Tools.Extract(gamepath + @"mdata\m999\rom\gm_pv_list_tbl");
  340. }
  341. pv_orig.SaveTo(gamepath + @"mdata\m999\rom\pv_db.txt");
  342. pv_field.SaveTo(gamepath + @"mdata\m999\rom\pv_field.txt");
  343. spritedb.Save(gamepath + @"mdata\m999\rom\2d\mdata_spr_db.bin");
  344. }
  345. else
  346. {
  347. if (!isConsole)
  348. {
  349. pv_list.SaveTo(gamepath + @"rom\gm_pv_list_tbl\gm_pv_list.bin");
  350. Tools.Extract(gamepath + @"rom\gm_pv_list_tbl");
  351. }
  352. pv_orig.SaveTo(gamepath + @"rom\pv_db.txt");
  353. pv_field.SaveTo(gamepath + @"rom\pv_field.txt");
  354. }
  355. if (forcemod)
  356. {
  357. //delete divamods backup, set current as base
  358. }
  359. //done?
  360. }
  361. }
  362. }