static void Main(string [] param) { if (param.Length >= 1) { if (param[0].Equals("-scanroms", StringComparison.CurrentCultureIgnoreCase)) { GameDBMgr.DoScanWithoutUI(param[1]); } else if (param[0].Equals("-convertimg", StringComparison.CurrentCultureIgnoreCase)) { GameDBMgr.ConvertImages(); } else { Console.WriteLine("Command Line usage:"); Console.WriteLine(); Console.WriteLine("GameDbManager [-scanroms directory_name|-convertimg]"); } return; } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new GameDBMgr()); }
private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofn = new OpenFileDialog(); ofn.CheckPathExists = true; ofn.Multiselect = false; ofn.Filter = "HuCard Files (*.pce)|*.pce|CDRom cuesheets (*.cue)|*.cue"; if (ofn.ShowDialog() == DialogResult.OK) { uint crc; if (ofn.FileName.EndsWith(".pce", StringComparison.InvariantCultureIgnoreCase)) { var data = File.ReadAllBytes(ofn.FileName); if ((data.Length & 0xFFF) != 0) { uint l = (uint)data.Length & 0xFFFFF000; var dat = new byte[l]; Array.Copy(data, data.Length & 0xFFF, dat, 0, l); data = dat; crc = Crc32.Compute(data); } else { crc = Crc32.Compute(data); } } else if (ofn.FileName.EndsWith(".cue", StringComparison.InvariantCultureIgnoreCase)) { var cue = new CueSheet(ofn.FileName); crc = GameDBMgr.ComputeCueCrc(cue); } else { MessageBox.Show("Invalid file extension"); return; } //Check if the crc already exists String crcstr = crc.ToString("X8"); var ck = gameDB.GameCk.FirstOrDefault(x => x.Checksum == crcstr); if (ck != null) { if (ck.GameID == gameID) { MessageBox.Show("This checksum already exists for this game"); } else { MessageBox.Show("This checksum already exists for a different game!!"); } } else { ck = gameDB.GameCk.NewGameCkRow(); ck.GameID = gameID; ck.Checksum = crcstr; gameDB.GameCk.AddGameCkRow(ck); } } }
static void ScanDir(String dir, GameDB db, GameDBMgr form) { Game[] games; byte[] scshots; ushort sccnt; ushort gamecnt; int crptBlock; gamecnt = 0; sccnt = 0; crptBlock = 0; games = new Game[1024]; scshots = new Byte[1024 * 3072]; if (form != null) { form.Invoke(new Action(() => { form.label1.Text = Path.GetFileName(dir); })); } else { Console.WriteLine("Processing directory " + Path.GetFileName(dir)); } foreach (var f in Directory.GetFiles(dir, "*.pce")) { var data = File.ReadAllBytes(f); var crc = Crc32.Compute(data); var ck = db.GameCk.FirstOrDefault(w => w.Checksum == crc.ToString("X8")); if (ck == null && (data.Length & 0xFFF) != 0) { uint l = (uint)data.Length & 0xFFFFF000; var dat = new byte[l]; Array.Copy(data, data.Length & 0xFFF, dat, 0, l); data = dat; crc = Crc32.Compute(data); ck = db.GameCk.FirstOrDefault(w => w.Checksum == crc.ToString("X8")); } if (ck != null) { //var namecrc = Crc32.Compute(Encoding.ASCII.GetBytes(f.Substring(f.LastIndexOf('\\') + 1))); var nn = f.Substring(f.LastIndexOfAny(new char[] { '\\', '/' }) + 1); nn = nn.Substring(0, nn.LastIndexOf('.')); var name = Encoding.ASCII.GetBytes(nn); byte[] namecnv = new byte[56]; if (name.Length > 56) { Array.Copy(name, namecnv, 56); } else { Array.Copy(name, namecnv, name.Length); } for (int i = 0; i < namecnv.Length; ++i) { namecnv[i] = ProcessChar(namecnv[i]); } var namecrc = Crc32.update_crc(0xFFFFFFFF, namecnv, 56); var existing = games.Take(gamecnt).FirstOrDefault(x => x.checksum != 0 && x.GameID == ck.GameID); if (existing != null) { var g = new Game(); g.checksum = namecrc; g.remap = existing.remap; g.GameID = existing.GameID; g.TextName = existing.TextName; g.ScreenName = existing.ScreenName; games[gamecnt] = g; ++gamecnt; } else { var gg = db.Game.FirstOrDefault(x => x.ID == ck.GameID); if (gg != null && !gg.IsScreenshotNull()) { //String dst = "TileCache/" + gg.Screenshot.Substring(gg.Screenshot.LastIndexOfAny(new char[] { '\\', '/' }) + 1); string dst = "TileCache/" + gg.Screenshot.Replace("\\", "_").Replace("/", "_").Replace(":", "_"); dst = dst.Replace(".png", ".tile"); if (File.Exists(dst)) { var g = new Game(); g.checksum = namecrc; g.remap = sccnt; g.GameID = ck.GameID; g.TextName = gg.Name; g.ScreenName = gg.Screenshot; games[gamecnt] = g; ++gamecnt; //copy screenshot to the scshot block byte[] scshot = File.ReadAllBytes(dst); byte[] scshot2 = new byte[3072]; Array.Copy(scshot, scshot2, scshot.Length); //add year, genre... scshot2[0xA00] = 0x0; //version if (!gg.IsGenreNull()) { scshot2[0xA01] = (byte)gg.Genre; } if (!gg.IsYearNull()) { scshot2[0xA02] = (byte)(gg.Year & 0xFF); scshot2[0xA03] = (byte)((gg.Year >> 8) & 0xFF); } Debug.Assert(scshot2.Length == 3072); Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); // The issue is there is a sequence of screenshot indexes that the lookup fails to // resolve to the right location displaying junk data as the screenshot // This is the sequence // Index: 0 21 42 64 85 106 128 149 170 192 // Spacing: 21 21 22 21 21 22 21 21 22 ... // // A repeating pattern of 21, 21, 22... if (((sccnt - crptBlock) % 21 == 0) && ((sccnt + 1) % 64 != 0)) { // true Console.WriteLine("Corrupted Index Skipped: {0}", sccnt); sccnt++; games[gamecnt - 1].remap = sccnt; Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); } else if (sccnt % 64 == 0) { // true Console.WriteLine("Corrupted Index Skipped: {0}", sccnt); sccnt++; games[gamecnt - 1].remap = sccnt; Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); crptBlock++; } else { // false. do nothing } sccnt++; } } } } else { //Console.WriteLine("Missing crc " + f); } } //scan dirs for cds foreach (var d in Directory.GetDirectories(dir)) { var cues = Directory.GetFiles(d, "*.cue"); if (cues.Length == 1) { try { var cue = new CueSheet(cues[0]); var crc = ComputeCueCrc(cue); var ck = db.GameCk.FirstOrDefault(w => w.Checksum == crc.ToString("X8")); if (ck != null) { //var namecrc = Crc32.Compute(Encoding.ASCII.GetBytes(f.Substring(f.LastIndexOf('\\') + 1))); var nn = d.Substring(d.LastIndexOfAny(new char[] { '\\', '/' }) + 1); var name = Encoding.ASCII.GetBytes(nn); byte[] namecnv = new byte[56]; if (name.Length > 56) { Array.Copy(name, namecnv, 56); } else { Array.Copy(name, namecnv, name.Length); } for (int i = 0; i < namecnv.Length; ++i) { namecnv[i] = ProcessChar(namecnv[i]); } var namecrc = Crc32.update_crc(0xFFFFFFFF, namecnv, 56); var existing = games.Take(gamecnt).FirstOrDefault(x => x.checksum != 0 && x.GameID == ck.GameID); if (existing != null) { var g = new Game(); g.checksum = namecrc; g.remap = existing.remap; g.GameID = existing.GameID; g.TextName = existing.TextName; g.ScreenName = existing.ScreenName; games[gamecnt] = g; ++gamecnt; } else { var gg = db.Game.FirstOrDefault(x => x.ID == ck.GameID); if (gg != null && !gg.IsScreenshotNull()) { //String dst = "TileCache/" + gg.Screenshot.Substring(gg.Screenshot.LastIndexOfAny(new char[] { '\\', '/' }) + 1); string dst = "TileCache/" + gg.Screenshot.Replace("\\", "_").Replace("/", "_").Replace(":", "_"); dst = dst.Replace(".png", ".tile"); if (File.Exists(dst)) { var g = new Game(); g.checksum = namecrc; g.remap = sccnt; g.GameID = ck.GameID; g.TextName = gg.Name; g.ScreenName = gg.Screenshot; games[gamecnt] = g; ++gamecnt; //copy screenshot to the scshot block byte[] scshot = File.ReadAllBytes(dst); byte[] scshot2 = new byte[3072]; Array.Copy(scshot, scshot2, scshot.Length); //add year, genre... scshot2[0xA00] = 0x0; //version if (!gg.IsGenreNull()) { scshot2[0xA01] = (byte)gg.Genre; } if (!gg.IsYearNull()) { scshot2[0xA02] = (byte)(gg.Year & 0xFF); scshot2[0xA03] = (byte)((gg.Year >> 8) & 0xFF); } Debug.Assert(scshot2.Length == 3072); Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); // Bad index patch if (((sccnt - crptBlock) % 21 == 0) && ((sccnt + 1) % 64 != 0)) { // true Console.WriteLine("Corrupted Index Skipped: {0}", sccnt); sccnt++; games[gamecnt - 1].remap = sccnt; Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); } else if (sccnt % 64 == 0) { // true Console.WriteLine("Corrupted Index Skipped: {0}", sccnt); sccnt++; games[gamecnt - 1].remap = sccnt; Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); crptBlock++; } else { // false. do nothing } sccnt++; } } } } else { //Console.WriteLine("Missing crc " + f); } } catch (Exception ex) { Console.WriteLine("Error processing " + cues[0] + " . Skipped"); Console.WriteLine(ex.Message); } } } if (gamecnt != 0) { games = games.Take(gamecnt).OrderBy(x => x.checksum).ToArray(); //Console.WriteLine("Writting game.db"); List <string> debugOutput = new List <string>(); //Console.WriteLine("{0,8} {1,8} {2,10} {3,4} {4,-32} {5,-32}", "Little", "Big", "Int", "Indx", "DB Text Name", "Screenshot"); debugOutput.Add(String.Format("{0,8},{1,8},{2,10},{3,4},{4,-32},{5,-32}", "Little", "Big", "Int", "Indx", "DB Text Name", "Screenshot")); FileStream fs = new FileStream(dir + "/games.db", FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs); foreach (var g in games) { bw.Write(g.checksum); // TODO: Add Debug Check string shortName = g.TextName.Length > 31 ? g.TextName.Substring(0, 31) : g.TextName; //Console.WriteLine("{0,8} {1,8} {2,10} {3,4} {4,-32} {5,-32}", LittleEndian(g.checksum.ToString("X8")), g.checksum.ToString("X8"), g.checksum, g.remap, shortName, g.ScreenName); debugOutput.Add(String.Format("{0,8},{1,8},{2,10},{3,4},{4,-32},{5,-32}", LittleEndian(g.checksum.ToString("X8")), g.checksum.ToString("X8"), g.checksum, g.remap, shortName, g.ScreenName)); } if (form.debugToolStripMenuItem.Checked) { foreach (string d in debugOutput) { Console.WriteLine(d.Replace(',', ' ')); } System.IO.File.WriteAllLines(dir + "/debug.csv", debugOutput.ToArray()); } for (int i = 0; i < 1024 - games.Length; ++i) { bw.Write(0xFFFFFFFF); } foreach (var g in games) { bw.Write(g.remap); } for (int i = 0; i < 1024 - games.Length; ++i) { bw.Write((ushort)0xFFFF); } bw.Write(scshots, 0, 3072 * sccnt); bw.Close(); fs.Close(); } foreach (var d in Directory.GetDirectories(dir)) { ScanDir(d, db, form); } }
static void ScanDir(String dir, GameDB db, GameDBMgr form) { Game[] games; byte[] scshots; ushort sccnt; ushort gamecnt; gamecnt = 0; sccnt = 0; games = new Game[1024]; scshots = new Byte[1024 * 3072]; if (form != null) { form.Invoke(new Action(() => { form.label1.Text = Path.GetFileName(dir); })); } else { Console.WriteLine("Processing directory " + Path.GetFileName(dir)); } foreach (var f in Directory.GetFiles(dir, "*.pce")) { var data = File.ReadAllBytes(f); var crc = Crc32.Compute(data); var ck = db.GameCk.FirstOrDefault(w => w.Checksum == crc.ToString("X8")); if (ck == null && (data.Length & 0xFFF) != 0) { uint l = (uint)data.Length & 0xFFFFF000; var dat = new byte[l]; Array.Copy(data, data.Length & 0xFFF, dat, 0, l); data = dat; crc = Crc32.Compute(data); ck = db.GameCk.FirstOrDefault(w => w.Checksum == crc.ToString("X8")); } if (ck != null) { //var namecrc = Crc32.Compute(Encoding.ASCII.GetBytes(f.Substring(f.LastIndexOf('\\') + 1))); var nn = f.Substring(f.LastIndexOfAny(new char[] { '\\', '/' }) + 1); nn = nn.Substring(0, nn.LastIndexOf('.')); var name = Encoding.ASCII.GetBytes(nn); byte[] namecnv = new byte[56]; if (name.Length > 56) { Array.Copy(name, namecnv, 56); } else { Array.Copy(name, namecnv, name.Length); } for (int i = 0; i < namecnv.Length; ++i) { namecnv[i] = ProcessChar(namecnv[i]); } var namecrc = Crc32.update_crc(0xFFFFFFFF, namecnv, 56); var existing = games.Take(gamecnt).FirstOrDefault(x => x.checksum != 0 && x.GameID == ck.GameID); if (existing != null) { var g = new Game(); g.checksum = namecrc; g.remap = existing.remap; g.GameID = existing.GameID; games[gamecnt] = g; ++gamecnt; } else { var gg = db.Game.FirstOrDefault(x => x.ID == ck.GameID); if (gg != null && !gg.IsScreenshotNull()) { //String dst = "TileCache/" + gg.Screenshot.Substring(gg.Screenshot.LastIndexOfAny(new char[] { '\\', '/' }) + 1); string dst = "TileCache/" + gg.Screenshot.Replace("\\", "_").Replace("/", "_").Replace(":", "_"); dst = dst.Replace(".png", ".tile"); if (File.Exists(dst)) { var g = new Game(); g.checksum = namecrc; g.remap = sccnt; g.GameID = ck.GameID; games[gamecnt] = g; ++gamecnt; //copy screenshot to the scshot block byte[] scshot = File.ReadAllBytes(dst); byte[] scshot2 = new byte[3072]; Array.Copy(scshot, scshot2, scshot.Length); //add year, genre... scshot2[0xA00] = 0x0; //version if (!gg.IsGenreNull()) { scshot2[0xA01] = (byte)gg.Genre; } if (!gg.IsYearNull()) { scshot2[0xA02] = (byte)(gg.Year & 0xFF); scshot2[0xA03] = (byte)((gg.Year >> 8) & 0xFF); } Debug.Assert(scshot2.Length == 3072); Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); sccnt++; } } } } else { //Console.WriteLine("Missing crc " + f); } } //scan dirs for cds foreach (var d in Directory.GetDirectories(dir)) { var cues = Directory.GetFiles(d, "*.cue"); if (cues.Length == 1) { try { var cue = new CueSheet(cues[0]); var crc = ComputeCueCrc(cue); var ck = db.GameCk.FirstOrDefault(w => w.Checksum == crc.ToString("X8")); if (ck != null) { //var namecrc = Crc32.Compute(Encoding.ASCII.GetBytes(f.Substring(f.LastIndexOf('\\') + 1))); var nn = d.Substring(d.LastIndexOfAny(new char[] { '\\', '/' }) + 1); var name = Encoding.ASCII.GetBytes(nn); byte[] namecnv = new byte[56]; if (name.Length > 56) { Array.Copy(name, namecnv, 56); } else { Array.Copy(name, namecnv, name.Length); } for (int i = 0; i < namecnv.Length; ++i) { namecnv[i] = ProcessChar(namecnv[i]); } var namecrc = Crc32.update_crc(0xFFFFFFFF, namecnv, 56); var existing = games.Take(gamecnt).FirstOrDefault(x => x.checksum != 0 && x.GameID == ck.GameID); if (existing != null) { var g = new Game(); g.checksum = namecrc; g.remap = existing.remap; g.GameID = existing.GameID; games[gamecnt] = g; ++gamecnt; } else { var gg = db.Game.FirstOrDefault(x => x.ID == ck.GameID); if (gg != null && !gg.IsScreenshotNull()) { //String dst = "TileCache/" + gg.Screenshot.Substring(gg.Screenshot.LastIndexOfAny(new char[] { '\\', '/' }) + 1); string dst = "TileCache/" + gg.Screenshot.Replace("\\", "_").Replace("/", "_").Replace(":", "_"); dst = dst.Replace(".png", ".tile"); if (File.Exists(dst)) { var g = new Game(); g.checksum = namecrc; g.remap = sccnt; g.GameID = ck.GameID; games[gamecnt] = g; ++gamecnt; //copy screenshot to the scshot block byte[] scshot = File.ReadAllBytes(dst); byte[] scshot2 = new byte[3072]; Array.Copy(scshot, scshot2, scshot.Length); //add year, genre... scshot2[0xA00] = 0x0; //version if (!gg.IsGenreNull()) { scshot2[0xA01] = (byte)gg.Genre; } if (!gg.IsYearNull()) { scshot2[0xA02] = (byte)(gg.Year & 0xFF); scshot2[0xA03] = (byte)((gg.Year >> 8) & 0xFF); } Debug.Assert(scshot2.Length == 3072); Array.Copy(scshot2, 0, scshots, 3072 * sccnt, scshot2.Length); sccnt++; } } } } else { //Console.WriteLine("Missing crc " + f); } } catch (Exception ex) { Console.WriteLine("Error processing " + cues[0] + " . Skipped"); Console.WriteLine(ex.Message); } } } if (gamecnt != 0) { games = games.Take(gamecnt).OrderBy(x => x.checksum).ToArray(); //Console.WriteLine("Writting game.db"); FileStream fs = new FileStream(dir + "/games.db", FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs); foreach (var g in games) { bw.Write(g.checksum); } for (int i = 0; i < 1024 - games.Length; ++i) { bw.Write(0xFFFFFFFF); } foreach (var g in games) { bw.Write(g.remap); } for (int i = 0; i < 1024 - games.Length; ++i) { bw.Write((ushort)0xFFFF); } bw.Write(scshots, 0, 3072 * sccnt); bw.Close(); fs.Close(); } foreach (var d in Directory.GetDirectories(dir)) { ScanDir(d, db, form); } }