// gathered enough data, let's go static bool BuildROMS() { // how big is our output array? uint finalSize = HEADER_SIZE; //8kb // add the ROM files too.. for (int i = 0; i < roms.Count; i++) { finalSize += roms[i].paddedLength; } Console.WriteLine("\nBuilding index...\n"); #if DEBUG_ARGS Console.WriteLine("\n Final Size: " + finalSize + " (0x" + finalSize.ToString("X8") + ")\n"); #endif // Not going to use a binary writer here to keep the code as portable as possible byte[] writeBytes = new byte[finalSize]; // Better keeping separate vars for both than inlining it // for debugging uint headerOffset = 0; uint dataOffset = 0; for (int i = 0; i < roms.Count; i++) { ROMEntry rom = roms[i]; // 0x00 to 0x10 -> Header headerOffset = WriteLittleEndian(rom.actualLength, writeBytes, headerOffset); headerOffset = WriteLittleEndian(rom.offset, writeBytes, headerOffset); headerOffset = WriteLittleEndian(rom.checkSum, writeBytes, headerOffset); headerOffset = WriteLittleEndian(0, writeBytes, headerOffset); // name stored in the rom? string nameSource = useInternalNameSort ? rom.internalName : rom.fileName; // 45 chars for description, pad with 0's after we read past the length for (int b = 0; b < FILENAME_LIMIT; b++) { writeBytes[headerOffset++] = (b < nameSource.Length) ? (byte)nameSource[b] : (byte)0; } // 3 final zeros writeBytes[headerOffset++] = 0; writeBytes[headerOffset++] = 0; writeBytes[headerOffset++] = 0; dataOffset = rom.offset; // and write the file for (int b = 0; b < rom.paddedLength; b++) { if (b < rom.actualLength) { writeBytes[dataOffset + b] = rom.paddedData[b]; } else { // could write zero, but c# inits to 0 anyway } } } // this is not time-traveller-proof TimeSpan startSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1)); // shortest way to represent the epoch? double lastReadTime = startSpan.TotalSeconds; if (File.Exists(targetFilename)) { PrintWarning("Filename already exists: " + targetFilename); try{ if (File.Exists(targetFilename + "_BACKUP")) { File.Delete(targetFilename + "_BACKUP"); } File.Move(targetFilename, targetFilename + "_BACKUP"); PrintWarning("Renamed " + targetFilename + " to " + targetFilename + "_BACKUP"); } catch (System.Exception e) { PrintWarning("Could not rename the existing file... " + e); targetFilename += lastReadTime + ".DAT"; PrintWarning("Using alternate filename: " + targetFilename); } } try{ File.WriteAllBytes(targetFilename, writeBytes); } catch (Exception e) { PrintError("Error writing to disk: " + e); return(false); } if (numWarnings > 0) { Console.Write("\n\n Build completed successfully with warnings!\n\n"); WaitKey(); } else { Console.Write("\n\n Build completed successfully with no warnings!\n\n"); } return(true); }
static bool VerifyROMS() { // Get a list of .ROM files + Verify string currentDirectory = ""; try{ currentDirectory = Directory.GetCurrentDirectory(); } catch (Exception e) { // UnathorisedAccessException or NotSupportedException officially // but best to print it anyway. PrintError("Exception: " + e); return(false); } // instead of maintaining separate arrays, let's stick it in a list // and cross them off one by one romFileNames = new List <string>(); try{ // C# really spoils us sometimes... romFileNames = Directory.GetFiles(currentDirectory).OrderByDescending(f => f).ToList <string>(); } catch (Exception e) { // Again, a bunch of possible errors, but given // the low importance, let's just print it and move on. PrintError("Exception " + e); return(false); } // Filter by extension // Todo: add .bin? for (int i = romFileNames.Count - 1; i >= 0; i--) { if (!romFileNames[i].ToUpperInvariant().EndsWith(".ROM")) { romFileNames.RemoveAt(i); continue; } Console.WriteLine("Found: " + Path.GetFileNameWithoutExtension(romFileNames[i])); } if (romFileNames.Count == 0) { PrintError("Didn't find any ROMs!"); return(false); } if (romFileNames.Count > 128) { PrintError("Sorry, the limit is 128 ROM files!"); return(false); } // Init the list of byte arrays roms = new List <ROMEntry>(); // we can keep a running tally of this now UInt32 romOffset = HEADER_SIZE; // Filter by what is actually a ROM // since we're already opening them to check, hold them in RAM for (int i = romFileNames.Count - 1; i >= 0; i--) { Console.WriteLine("\nChecking: " + romFileNames[i]); byte[] romData; try{ romData = File.ReadAllBytes(romFileNames[i]); } catch (Exception e) { PrintError("Exception reading file: " + romFileNames[i]); PrintError("The exception returned was: " + e); PrintError("Skipping that file..."); continue; } // let's verify the header // the first header is optional at 0x04, the original romfile.exe did not take account of this // instead we'll be using the second header at 0x84 - 0xB0 (exclusive) // which should read "Licensed by Sony Computer Entertainment Inc." // checksum it. // technically there could be code in just the header gaps // nocash has put code there, paul, and smartcart patches like Ahoy too if (romData.Length < 0xB0) { PrintError("Not a valid rom! " + romFileNames[i]); continue; } UInt32 paddedLength = (uint)romData.Length; if (romData.Length % SECTOR_SIZE > 0) { paddedLength += SECTOR_SIZE - (paddedLength % SECTOR_SIZE); Console.WriteLine("padding size from " + romData.Length.ToString("X") + " to " + paddedLength.ToString("X")); } UInt32 licenseChecksum = 0; UInt32 romChecksum = 0; for (int b = 0; b < romData.Length; b++) { if (b >= 0x84 && b < 0xB0) { licenseChecksum += romData[b]; } romChecksum += romData[b];; } bool normalByteOrder = (licenseChecksum == 0x1040); bool reverseByteOrder = (licenseChecksum == 0x1498); if (normalByteOrder || reverseByteOrder) { Console.WriteLine("Checksum " + licenseChecksum.ToString("X") + " reversed?=" + reverseByteOrder); } else { PrintWarning("Could not find the license string!"); continue; } #if DEBUG_ARGS Console.WriteLine(" File checksum is 0x" + licenseChecksum.ToString("X8")); #endif // So not portable,but look how neat it is. string fileName = Path.GetFileNameWithoutExtension(romFileNames[i]); fileName = fileName.Replace("[!]", ""); // For SquareSoft74's sanity fileName = fileName.Substring(0, Math.Min(FILENAME_LIMIT, fileName.Length)); string internalName = GetInternalName(fileName, romData, reverseByteOrder); internalName = internalName.Substring(0, Math.Min(FILENAME_LIMIT, internalName.Length)); // not a fan of this setup as it makes searching for ".fileName" a little // awkward, but equally I hate huge constructors. Thoughts? ROMEntry rom = new ROMEntry() { actualLength = (UInt32)romData.Length, offset = romOffset, // haven't sorted the list so we don't know this yet checkSum = romChecksum, paddedData = romData, paddedLength = paddedLength, fileName = fileName, internalName = internalName }; romOffset += paddedLength; roms.Add(rom); } if (roms.Count == 0) { PrintError("None of those ROMs were valid!"); return(false); } return(true); }