El programa SaveDataFiler cuando exporta las partidas guardadas lo hace dentro de una carpeta cuyo nombre es un timestamp y dentro de ella otra carpeta y ficheros con nombre del ID del juego. Eso hace que sea complicado saber qué carpeta es de cada juego y sea necesario consultarlo en internet.
Por ello he creado un sencillo programa que hace una copia de esas carpetas pero con un nuevo nombre en el que se incluye la fecha, ID del juego, nombre del juego y la región. Solo hay que ejecutarlo dentro de la carpeta UserSaveData o ExtDataBoss o ExtData, dentro de la MicroSD o haciendo una copia antes en el PC, y en unos segundos hará la tarea de renombrar todo.
Los datos de los juegos están almacenados dentro del propio .exe por lo que no hace falta ningún fichero mas, sin embargo, esa base de datos interna puede quedarse anticuada si salen nuevos juegos, actualmente tiene hasta el juego 2289 Gudetama: Okawari Ikagassuka, para solventar esto sera necesario descargar el fichero XML desde 3dsdb.com en el enlace Download XML y situarlo junto al .exe, de este modo el programa dará prioridad al XML en vez de a los datos internos.
El código del programa es el siguiente, por si alguien tiene curiosidad o quiere mejorarlo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
using System; using System.IO; using System.Collections.Generic; using System.Xml; using System.Text.RegularExpressions; using System.Globalization; using SaveDataFiler_AutoRename.Properties; namespace RenameSaves { class RenameSaves { static void Main(string[] args) { //GET EXECUTION DIRECTORY: String exeName = System.AppDomain.CurrentDomain.FriendlyName.Replace(".vshost", ""); String workingPath = System.Reflection.Assembly.GetEntryAssembly().Location.Replace(exeName, ""); //OPEN XML GAME DATABASE AND PARSE TO OBJECT: Dictionary<String, Game> games = new Dictionary<string, Game>(); Game game; XmlDocument xDoc = new XmlDocument(); if (File.Exists(workingPath + "3dsreleases.xml")) xDoc.Load(workingPath + "3dsreleases.xml"); else xDoc.LoadXml(Resources._3dsreleases); XmlNodeList xmlReleases = xDoc.GetElementsByTagName("release"); String id = "", name = "", publisher = "", region = "", languages = "", group = "", imagesize = "", serial = "", titleid = "", imgcrc = "", filename = "", releasename = "", trimmedsize = "", firmware = "", type = "", card = ""; foreach (XmlElement release in xmlReleases) { foreach (XmlElement attributes in release.ChildNodes) { switch (attributes.Name) { case "id": id = attributes.InnerText; break; case "name": name = attributes.InnerText; break; case "publisher": publisher = attributes.InnerText; break; case "region": region = attributes.InnerText; break; case "languages": languages = attributes.InnerText; break; case "group": group = attributes.InnerText; break; case "imagesize": imagesize = attributes.InnerText; break; case "serial": serial = attributes.InnerText; break; case "titleid": titleid = attributes.InnerText; break; case "imgcrc": imgcrc = attributes.InnerText; break; case "filename": filename = attributes.InnerText; break; case "releasename": releasename = attributes.InnerText; break; case "trimmedsize": trimmedsize = attributes.InnerText; break; case "firmware": firmware = attributes.InnerText; break; case "type": type = attributes.InnerText; break; case "card": card = attributes.InnerText; break; } } game = new Game(id, name, publisher, region, languages, group, imagesize, serial, titleid, imgcrc, filename, releasename, trimmedsize, firmware, type, card); if (game.titleidShort != null && game.titleidShort.Length > 0 && !games.ContainsKey(game.titleidShort)) games.Add(game.titleidShort, game); } //COPY DATA IN NEW FOLDER: String[] savesDates = Directory.GetDirectories(workingPath); foreach (String saveDate in savesDates) { String date = saveDate.Remove(0, workingPath.Length); if (date.Length == 14) { String[] saveDateIDs = Directory.GetDirectories(saveDate); String saveID = null; foreach (String saveDateID in saveDateIDs) saveID = saveDateID.Remove(0, saveDate.Length + 1); if (saveID != null) { saveID = saveID.ToUpper().Substring(3, 5); if (games.ContainsKey(saveID)) { game = games[saveID]; game.name = Regex.Replace(game.name, @"\*|\||\\|\:|\"" |\<|\>|\?|\/ ", ""); String dirName = DateTime.ParseExact(date, "yyyyMMddHHmmss", CultureInfo.InvariantCulture).ToString("yyyy-MM-dd HH.mm.ss") + " - " + game.titleidShort + " - " + game.name + " " + game.region; String destDirName = workingPath + "OUTPUT" + Path.DirectorySeparatorChar + dirName; DirectoryCopy(saveDate, destDirName, true); } else { DirectoryCopy(saveDate, workingPath + "OUTPUT" + Path.DirectorySeparatorChar + date, true); } } } } } /** * https://msdn.microsoft.com/en-us/library/bb762914(v=vs.110).aspx */ private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs) { // Get the subdirectories for the specified directory. DirectoryInfo dir = new DirectoryInfo(sourceDirName); if (!dir.Exists) throw new DirectoryNotFoundException("Source directory does not exist or could not be found: " + sourceDirName); DirectoryInfo[] dirs = dir.GetDirectories(); // If the destination directory doesn't exist, create it. if (!Directory.Exists(destDirName)) Directory.CreateDirectory(destDirName); // Get the files in the directory and copy them to the new location. FileInfo[] files = dir.GetFiles(); foreach (FileInfo file in files) { string temppath = Path.Combine(destDirName, file.Name); file.CopyTo(temppath, true); } // If copying subdirectories, copy them and their contents to new location. if (copySubDirs) { foreach (DirectoryInfo subdir in dirs) { string temppath = Path.Combine(destDirName, subdir.Name); DirectoryCopy(subdir.FullName, temppath, copySubDirs); } } } } } |