diff --git a/dspatch/DS/DemoMenu.cs b/dspatch/DS/DemoMenu.cs index 00f7528..9da14f9 100644 --- a/dspatch/DS/DemoMenu.cs +++ b/dspatch/DS/DemoMenu.cs @@ -14,7 +14,7 @@ namespace dspatch.DS { MemoryStream m = new MemoryStream(); EndianBinaryWriter er = new EndianBinaryWriter(m); - er.Write((byte)entries.Length); + er.Write((byte)entries.Count); er.Write((byte)0); er.Write((byte)0); er.Write((byte)0); @@ -25,7 +25,7 @@ namespace dspatch.DS er.Close(); return result; } - public DemoMenuEntry[] entries; + public List entries = new List(); public class DemoMenuEntry { private string createString(string text, int length, bool nullTerminated = true) diff --git a/dspatch/DownloadStationPatcher.cs b/dspatch/DownloadStationPatcher.cs new file mode 100644 index 0000000..eef846b --- /dev/null +++ b/dspatch/DownloadStationPatcher.cs @@ -0,0 +1,278 @@ +using dspatch.DS; +using dspatch.IO; +using dspatch.Nitro; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace dspatch +{ + public class DownloadStationPatcher + { + private static byte[] haxxStationIconImage = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x61, 0x66, 0x66, 0x69, 0x66, 0x66, 0x66, 0x61, 0xC8, 0xCC, 0xCC, + 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x16, 0x09, 0x66, 0x66, 0x66, 0x96, + 0xCC, 0xCC, 0x8C, 0x16, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xCC, 0xCC, 0x6C, + 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, + 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0x8C, 0xCC, 0x6C, 0x45, 0x65, 0x41, 0x85, + 0x89, 0xE2, 0xC0, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x27, 0x16, 0x54, 0xB7, 0xD5, 0xE0, 0x9D, 0x14, + 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, + 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0x99, 0xCC, 0x66, + 0x5C, 0x11, 0xC5, 0x66, 0x42, 0xEE, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x20, 0x0E, 0x00, + 0x00, 0x79, 0x00, 0x0B, 0x00, 0x01, 0x70, 0x08, 0xD0, 0x04, 0x2E, 0x00, + 0xB0, 0x07, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x77, 0x0C, + 0x24, 0x87, 0x52, 0x14, 0x66, 0x14, 0xC9, 0x6C, 0x66, 0xAC, 0xCC, 0x6C, + 0x66, 0xCC, 0xC1, 0x6C, 0x66, 0x1C, 0x16, 0x6C, 0x66, 0xCC, 0xC1, 0x6C, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0xA7, 0x00, 0x41, 0x88, 0x47, 0x41, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xF3, 0x63, 0x66, 0x66, + 0x36, 0x3F, 0x66, 0x66, 0x36, 0x3F, 0x66, 0x66, 0x0D, 0x00, 0xD0, 0x99, + 0x00, 0x88, 0x00, 0x00, 0x18, 0x44, 0x81, 0x99, 0x76, 0xCC, 0x57, 0x44, + 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0x6C, 0xCC, 0x66, 0xC6, 0xC6, 0xC6, 0x66, + 0xC6, 0x6C, 0xCC, 0x66, 0x90, 0x09, 0x89, 0x00, 0xB0, 0x07, 0x4D, 0x00, + 0xD0, 0x04, 0x10, 0x00, 0x00, 0x01, 0x80, 0x05, 0x00, 0x78, 0x00, 0x0E, + 0x00, 0x10, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, + 0x61, 0xC8, 0xCC, 0xCC, 0x68, 0x66, 0x66, 0x66, 0x80, 0x61, 0x66, 0x66, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x63, 0xFF, 0x6F, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCC, 0xCC, 0xCC, 0xCC, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, + 0xC6, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x8C, 0x16, 0x66, 0x66, 0x66, 0x86, + 0x66, 0x66, 0x16, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + private static byte[] haxxStationIconPltt = + { + 0x1F, 0x7C, 0x42, 0x04, 0x83, 0x0C, 0xC5, 0x08, 0xC6, 0x18, 0xE7, 0x1C, + 0x00, 0x00, 0x29, 0x25, 0x8C, 0x2D, 0xAD, 0x35, 0xCE, 0x39, 0x0F, 0x3E, + 0x10, 0x42, 0x51, 0x46, 0x94, 0x52, 0x35, 0x23 + }; + + private static byte[] haxxStationServer = + { + 0x52, 0x43, 0x31, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x30, 0x31, 0x20, + 0x32, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x72, 0x69, + 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00, 0x48, 0x61, 0x78, 0x78, 0x53, 0x74, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x79, 0x20, 0x47, 0x65, 0x72, + 0x69, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x73, 0x68, 0x75, 0x74, 0x74, 0x65, + 0x72, 0x62, 0x75, 0x67, 0x32, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x6E, 0x64, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x20, 0x54, 0x68, 0x75, 0x6E, 0x64, 0x65, 0x72, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + private static byte[] exploitData = + { + 0x44, 0x30, 0x9F, 0xE5, 0x2C, 0x00, 0x93, 0xE5, 0x2C, 0x10, 0x9F, 0xE5, + 0x01, 0x00, 0x40, 0xE0, 0x28, 0x10, 0x9F, 0xE5, 0x01, 0x00, 0x80, 0xE0, + 0x24, 0x10, 0x9F, 0xE5, 0x24, 0x20, 0x9F, 0xE5, 0x28, 0xE0, 0x9F, 0xE5, + 0x3E, 0xFF, 0x2F, 0xE1, 0x24, 0xE0, 0x9F, 0xE5, 0x3E, 0xFF, 0x2F, 0xE1, + 0x01, 0x00, 0xA0, 0xE3, 0x1C, 0xE0, 0x9F, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1, + 0x00, 0xAE, 0x11, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x6D, 0x11, 0x00, 0x40, 0xE8, 0x3F, 0x02, 0x08, 0xBB, 0x32, 0x02, + 0x24, 0xAF, 0x32, 0x02, 0x78, 0x3A, 0x32, 0x02 + }; + + private static byte[] arm7Fix = + { + 0x2C, 0x00, 0x9F, 0xE5, 0x8E, 0x07, 0x80, 0xE2, 0x1C, 0x10, 0x9F, 0xE5, + 0x1C, 0x20, 0x9F, 0xE5, 0x01, 0x30, 0xD0, 0xE4, 0x01, 0x30, 0xC1, 0xE4, + 0x01, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0xCA, 0x00, 0x00, 0x9F, 0xE5, + 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00 + }; + + private NDS mDownloadStation; + private SFSDirectory mFileSystem; + private DemoMenu mDemoMenu; + + public DownloadStationPatcher(NDS downloadStation) + { + mDownloadStation = downloadStation; + mFileSystem = mDownloadStation.ToFileSystem(); + + SFSDirectory d = mFileSystem.GetDirectoryByPath("//ds_demo"); + //this is shitty... + d.Files.Remove(d.GetFileByPath("ds_demo/ANDEdemo")); + d.Files.Remove(d.GetFileByPath("ds_demo/AGFEdemo")); + d.Files.Remove(d.GetFileByPath("ds_demo/AMFEclip")); + d.Files.Remove(d.GetFileByPath("ds_demo/AMTEdemo")); + d.Files.Remove(d.GetFileByPath("ds_demo/APTEdemo")); + d.Files.Remove(d.GetFileByPath("ds_demo/ATTEdemo")); + d.Files.Remove(d.GetFileByPath("ds_demo/ATTEpush")); + d.Files.Remove(d.GetFileByPath("ds_demo/testcode")); + d.Files.Remove(d.GetFileByPath("ds_demo/AMCEdemo")); + + mFileSystem.GetFileByPath("//mb/server").Data = haxxStationServer; + mFileSystem.GetFileByPath("//mb/icon.nbfc").Data = haxxStationIconImage; + mFileSystem.GetFileByPath("//mb/icon.nbfp").Data = haxxStationIconPltt; + + //change banner + mDownloadStation.Banner.Banner.Image = haxxStationIconImage; + mDownloadStation.Banner.Banner.Pltt = haxxStationIconPltt; + for (int i = 0; i < 6; i++) + mDownloadStation.Banner.Banner.GameName[i] = "HaxxStation\nBy Gericom, shutterbug2000\nand Apache Thunder"; + + mDemoMenu = new DemoMenu(); + } + + public void AddRom(NDS rom) + { + if (rom.Header.SubRamAddress >= 0x03000000) + { + byte[] newArm7 = new byte[rom.SubRom.Length + arm7Fix.Length]; + Array.Copy(arm7Fix, newArm7, arm7Fix.Length); + Array.Copy(rom.SubRom, 0, newArm7, arm7Fix.Length, rom.SubRom.Length); + IOUtil.WriteU32LE(newArm7, 0x28, rom.Header.SubEntryAddress); + IOUtil.WriteU32LE(newArm7, 0x2C, rom.Header.SubRamAddress); + IOUtil.WriteU32LE(newArm7, 0x30, rom.Header.SubSize); + rom.SubRom = newArm7; + rom.Header.SubSize = (uint)newArm7.Length; + rom.Header.SubRamAddress = 0x02380000; + rom.Header.SubEntryAddress = 0x02380000; + } + byte[] newRomFixed = rom.Write(true); + + uint arm9offset = (uint)(newRomFixed[0x20] | (newRomFixed[0x21] << 8) | (newRomFixed[0x22] << 16) | (newRomFixed[0x23] << 24)); + uint arm9loadaddr = (uint)(newRomFixed[0x28] | (newRomFixed[0x29] << 8) | (newRomFixed[0x2A] << 16) | (newRomFixed[0x2B] << 24)); + uint arm9size = (uint)(newRomFixed[0x2C] | (newRomFixed[0x2D] << 8) | (newRomFixed[0x2E] << 16) | (newRomFixed[0x2F] << 24)); + uint arm7offset = (uint)(newRomFixed[0x30] | (newRomFixed[0x31] << 8) | (newRomFixed[0x32] << 16) | (newRomFixed[0x33] << 24)); + + //arm9 offset becomes 0x180 + newRomFixed[0x20] = 0x80; + newRomFixed[0x21] = 0x01; + newRomFixed[0x22] = 0x00; + newRomFixed[0x23] = 0x00; + //arm9 load becomes 0x02332C40 (rsa_GetDecodedHash) + newRomFixed[0x28] = 0x40; + newRomFixed[0x29] = 0x2C; + newRomFixed[0x2A] = 0x33; + newRomFixed[0x2B] = 0x02; + //arm9 size becomes 0x100 + newRomFixed[0x2C] = 0x00; + newRomFixed[0x2D] = 0x01; + newRomFixed[0x2E] = 0x00; + newRomFixed[0x2F] = 0x00; + ushort newcrc = CRC16.GetCRC16(newRomFixed, 0, 0x15E); + newRomFixed[0x15E] = (byte)(newcrc & 0xFF); + newRomFixed[0x15F] = (byte)(newcrc >> 8); + + Array.Copy(exploitData, 0, newRomFixed, 0x180, exploitData.Length); + + newRomFixed[0x180 + 0x3C] = (byte)(arm7offset & 0xFF); + newRomFixed[0x180 + 0x3D] = (byte)((arm7offset >> 8) & 0xFF); + newRomFixed[0x180 + 0x3E] = (byte)((arm7offset >> 16) & 0xFF); + newRomFixed[0x180 + 0x3F] = (byte)((arm7offset >> 24) & 0xFF); + + newRomFixed[0x180 + 0x40] = (byte)(arm9offset & 0xFF); + newRomFixed[0x180 + 0x41] = (byte)((arm9offset >> 8) & 0xFF); + newRomFixed[0x180 + 0x42] = (byte)((arm9offset >> 16) & 0xFF); + newRomFixed[0x180 + 0x43] = (byte)((arm9offset >> 24) & 0xFF); + + newRomFixed[0x180 + 0x44] = (byte)(arm9loadaddr & 0xFF); + newRomFixed[0x180 + 0x45] = (byte)((arm9loadaddr >> 8) & 0xFF); + newRomFixed[0x180 + 0x46] = (byte)((arm9loadaddr >> 16) & 0xFF); + newRomFixed[0x180 + 0x47] = (byte)((arm9loadaddr >> 24) & 0xFF); + + newRomFixed[0x180 + 0x48] = (byte)(arm9size & 0xFF); + newRomFixed[0x180 + 0x49] = (byte)((arm9size >> 8) & 0xFF); + newRomFixed[0x180 + 0x4A] = (byte)((arm9size >> 16) & 0xFF); + newRomFixed[0x180 + 0x4B] = (byte)((arm9size >> 24) & 0xFF); + + string fileName = "rom" + mDemoMenu.entries.Count.ToString("0000") + "d"; + + var entry = new DemoMenu.DemoMenuEntry() + { + rating = 1, + guideMode = 0x15, + touchText1 = "HaxxStation by Gericom,", + touchText2 = "shutterbug2000, Apache Thunder", + internalName = fileName + }; + if (rom.Banner != null) + { + string[] lines = rom.Banner.Banner.GameName[1].Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + if (lines.Length > 0) + entry.bannerText1 = lines[0]; + else + entry.bannerText1 = "Bannerless Homebrew"; + if (lines.Length > 1) + entry.bannerText2 = lines[1]; + else + entry.bannerText2 = ""; + entry.bannerImage = rom.Banner.Banner.Image; + entry.bannerPalette = rom.Banner.Banner.Pltt; + } + else + { + entry.bannerText1 = "Bannerless Homebrew"; + entry.bannerText2 = ""; + entry.bannerImage = new byte[512]; + entry.bannerPalette = new byte[32]; + } + mDemoMenu.entries.Add(entry); + var d = mFileSystem.GetDirectoryByPath("//ds_demo"); + d.Files.Add(new SFSFile(-1, fileName, d) { Data = newRomFixed }); + + } + + public NDS ProduceRom() + { + string fileName = "rom" + (mDemoMenu.entries.Count - 1).ToString("0000") + "d"; + while (mDemoMenu.entries.Count < 3) + { + mDemoMenu.entries.Add(new DemoMenu.DemoMenuEntry() + { + bannerImage = new byte[512], + bannerPalette = new byte[32], + bannerText1 = "", + bannerText2 = "", + rating = 1, + guideMode = 0x15, + touchText1 = "HaxxStation by Gericom,", + touchText2 = "shutterbug2000, Apache Thunder", + internalName = fileName + }); + } + mFileSystem.GetFileByPath("//ds_demo/demomenu").Data = mDemoMenu.Write(); + mDownloadStation.FromFileSystem(mFileSystem); + return mDownloadStation; + } + } +} diff --git a/dspatch/Program.cs b/dspatch/Program.cs index 31a39ad..e021779 100644 --- a/dspatch/Program.cs +++ b/dspatch/Program.cs @@ -13,348 +13,116 @@ namespace dspatch { class Program { - static byte[] lockIconImage = - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x8A, - 0x00, 0xA0, 0x88, 0x88, 0x00, 0x88, 0x57, 0x34, 0x80, 0x58, 0x33, 0x33, - 0x8A, 0x34, 0x04, 0x00, 0xA0, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xA8, 0x0A, 0x00, 0x00, 0x88, 0x88, 0x0A, 0x00, - 0x43, 0x75, 0x88, 0x00, 0x33, 0x33, 0x85, 0x08, 0x00, 0x40, 0x43, 0x88, - 0x00, 0x00, 0x37, 0x85, 0x00, 0x00, 0x40, 0x73, 0x00, 0x00, 0x00, 0x53, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, - 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, - 0x00, 0x00, 0x00, 0x33, 0xDD, 0xDD, 0xDD, 0xDD, 0xA8, 0x00, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, - 0xDD, 0xED, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x29, 0xFF, 0xFF, 0xBF, 0x11, 0xFF, 0xFF, 0x9F, 0x11, - 0xFF, 0xFF, 0xBF, 0x11, 0xFF, 0xFF, 0xFF, 0x16, 0xDD, 0xDD, 0xDD, 0xDD, - 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x92, 0xDD, 0xDD, 0xDD, - 0x11, 0xDB, 0xDD, 0xDD, 0x11, 0xD9, 0xDD, 0xDD, 0x11, 0xDB, 0xDD, 0xDD, - 0x61, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, - 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, - 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, - 0xFF, 0xFF, 0xFF, 0x12, 0xFF, 0xFF, 0xCF, 0x11, 0xFF, 0xFF, 0x9F, 0x11, - 0xFF, 0xFF, 0x9F, 0x11, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0xDD, 0xDD, 0xDD, 0x21, 0xDD, 0xDD, 0xDD, - 0x11, 0xDB, 0xDD, 0xDD, 0x11, 0xD9, 0xDD, 0xDD, 0x11, 0xD9, 0xDD, 0xDD, - 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, - 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, - 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xDD, 0x00, 0x00, - 0xDD, 0xDD, 0x00, 0x00, 0xDD, 0xED, 0x00, 0x00 - }; - - static byte[] lockIconPltt = - { - 0x1C, 0x3C, 0x07, 0x25, 0x49, 0x25, 0xAA, 0x3D, 0xCB, 0x3D, 0xEC, 0x41, - 0xEF, 0x25, 0x0E, 0x4A, 0x2F, 0x4E, 0x74, 0x26, 0x71, 0x56, 0xF9, 0x2A, - 0x5B, 0x2F, 0x5E, 0x1B, 0x7E, 0x37, 0xBF, 0x2F - }; - - static byte[] haxxStationIconImage = - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x61, 0x66, 0x66, 0x69, 0x66, 0x66, 0x66, 0x61, 0xC8, 0xCC, 0xCC, - 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x16, 0x09, 0x66, 0x66, 0x66, 0x96, - 0xCC, 0xCC, 0x8C, 0x16, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xCC, 0xCC, 0x6C, - 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, - 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0x8C, 0xCC, 0x6C, 0x45, 0x65, 0x41, 0x85, - 0x89, 0xE2, 0xC0, 0x27, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x27, 0x16, 0x54, 0xB7, 0xD5, 0xE0, 0x9D, 0x14, - 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, - 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0x99, 0xCC, 0x66, - 0x5C, 0x11, 0xC5, 0x66, 0x42, 0xEE, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x20, 0x0E, 0x00, - 0x00, 0x79, 0x00, 0x0B, 0x00, 0x01, 0x70, 0x08, 0xD0, 0x04, 0x2E, 0x00, - 0xB0, 0x07, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x77, 0x0C, - 0x24, 0x87, 0x52, 0x14, 0x66, 0x14, 0xC9, 0x6C, 0x66, 0xAC, 0xCC, 0x6C, - 0x66, 0xCC, 0xC1, 0x6C, 0x66, 0x1C, 0x16, 0x6C, 0x66, 0xCC, 0xC1, 0x6C, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0xA7, 0x00, 0x41, 0x88, 0x47, 0x41, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xF3, 0x63, 0x66, 0x66, - 0x36, 0x3F, 0x66, 0x66, 0x36, 0x3F, 0x66, 0x66, 0x0D, 0x00, 0xD0, 0x99, - 0x00, 0x88, 0x00, 0x00, 0x18, 0x44, 0x81, 0x99, 0x76, 0xCC, 0x57, 0x44, - 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0x6C, 0xCC, 0x66, 0xC6, 0xC6, 0xC6, 0x66, - 0xC6, 0x6C, 0xCC, 0x66, 0x90, 0x09, 0x89, 0x00, 0xB0, 0x07, 0x4D, 0x00, - 0xD0, 0x04, 0x10, 0x00, 0x00, 0x01, 0x80, 0x05, 0x00, 0x78, 0x00, 0x0E, - 0x00, 0x10, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, 0x66, 0xCC, 0xCC, 0x6C, - 0x61, 0xC8, 0xCC, 0xCC, 0x68, 0x66, 0x66, 0x66, 0x80, 0x61, 0x66, 0x66, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x63, 0xFF, 0x6F, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCC, 0xCC, 0xCC, 0xCC, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC6, 0xCC, 0xCC, 0x66, 0xC6, 0xCC, 0xCC, 0x66, - 0xC6, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x8C, 0x16, 0x66, 0x66, 0x66, 0x86, - 0x66, 0x66, 0x16, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static byte[] haxxStationIconPltt = - { - 0x1F, 0x7C, 0x42, 0x04, 0x83, 0x0C, 0xC5, 0x08, 0xC6, 0x18, 0xE7, 0x1C, - 0x00, 0x00, 0x29, 0x25, 0x8C, 0x2D, 0xAD, 0x35, 0xCE, 0x39, 0x0F, 0x3E, - 0x10, 0x42, 0x51, 0x46, 0x94, 0x52, 0x35, 0x23 - }; - - static byte[] haxxStationServer = - { - 0x52, 0x43, 0x31, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x30, 0x31, 0x20, - 0x32, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x72, 0x69, - 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x00, 0x48, 0x61, 0x78, 0x78, 0x53, 0x74, - 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x79, 0x20, 0x47, 0x65, 0x72, - 0x69, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x73, 0x68, 0x75, 0x74, 0x74, 0x65, - 0x72, 0x62, 0x75, 0x67, 0x32, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x6E, 0x64, 0x20, 0x41, 0x70, - 0x61, 0x63, 0x68, 0x65, 0x20, 0x54, 0x68, 0x75, 0x6E, 0x64, 0x65, 0x72, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - static byte[] dsHash = { 0xF1, 0x8B, 0x55, 0xF3, 0xE1, 0x25, 0x9C, 0x03, 0xE1, 0x0D, 0x0E, 0xCB, 0x54, 0x96, 0x93, 0xB4, 0x29, 0x05, 0xCE, 0xB5 }; - static byte[] exploitData = - { - 0x44, 0x30, 0x9F, 0xE5, 0x2C, 0x00, 0x93, 0xE5, 0x2C, 0x10, 0x9F, 0xE5, - 0x01, 0x00, 0x40, 0xE0, 0x28, 0x10, 0x9F, 0xE5, 0x01, 0x00, 0x80, 0xE0, - 0x24, 0x10, 0x9F, 0xE5, 0x24, 0x20, 0x9F, 0xE5, 0x28, 0xE0, 0x9F, 0xE5, - 0x3E, 0xFF, 0x2F, 0xE1, 0x24, 0xE0, 0x9F, 0xE5, 0x3E, 0xFF, 0x2F, 0xE1, - 0x01, 0x00, 0xA0, 0xE3, 0x1C, 0xE0, 0x9F, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1, - 0x00, 0xAE, 0x11, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x20, 0x6D, 0x11, 0x00, 0x40, 0xE8, 0x3F, 0x02, 0x08, 0xBB, 0x32, 0x02, - 0x24, 0xAF, 0x32, 0x02, 0x78, 0x3A, 0x32, 0x02 - }; - - static byte[] arm7Fix = - { - 0x2C, 0x00, 0x9F, 0xE5, 0x8E, 0x07, 0x80, 0xE2, 0x1C, 0x10, 0x9F, 0xE5, - 0x1C, 0x20, 0x9F, 0xE5, 0x01, 0x30, 0xD0, 0xE4, 0x01, 0x30, 0xC1, 0xE4, - 0x01, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0xCA, 0x00, 0x00, 0x9F, 0xE5, - 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00 - }; - static void PrintUsage() { - Console.WriteLine("Usage: dspatch download_station.nds rom_to_boot.nds result.nds"); + Console.WriteLine("Usage: dspatch -s download_station.nds -o result.nds [-i rom1.nds] [-I romfolder1]"); + Console.WriteLine("You can add multiple roms by using -I or -i multiple times"); } static void Main(string[] args) { Console.WriteLine("== DS Download Station Patcher v1.0 =="); Console.WriteLine("Exploit by Gericom, shutterbug2000 and Apache Thunder\n"); - if (args.Length != 3) - PrintUsage(); - else + + if (args.Length <= 1) { - byte[] dsdata = File.ReadAllBytes(args[0]); - byte[] sha1 = SHA1.Create().ComputeHash(dsdata); - for (int i = 0; i < 20; i++) - { - if (sha1[i] != dsHash[i]) - { - Console.WriteLine("Error: Invalid download station rom!"); - Console.WriteLine("The patcher is only compatible with:"); - Console.WriteLine("xxxx - DS Download Station - Volume 1 (Kiosk WiFi Demo Cart) (U)(Independent).nds"); - Console.WriteLine("SHA1: F18B55F3E1259C03E10D0ECB549693B42905CEB5"); - return; - } - } - NDS downloadStation = new NDS(dsdata); - var fs = downloadStation.ToFileSystem(); - byte[] newRom = File.ReadAllBytes(args[1]); - NDS newRom2 = new NDS(newRom); - if (newRom2.Header.SubRamAddress >= 0x03000000) - { - byte[] newArm7 = new byte[newRom2.SubRom.Length + arm7Fix.Length]; - Array.Copy(arm7Fix, newArm7, arm7Fix.Length); - Array.Copy(newRom2.SubRom, 0, newArm7, arm7Fix.Length, newRom2.SubRom.Length); - IOUtil.WriteU32LE(newArm7, 0x28, newRom2.Header.SubEntryAddress); - IOUtil.WriteU32LE(newArm7, 0x2C, newRom2.Header.SubRamAddress); - IOUtil.WriteU32LE(newArm7, 0x30, newRom2.Header.SubSize); - newRom2.SubRom = newArm7; - newRom2.Header.SubSize = (uint)newArm7.Length; - newRom2.Header.SubRamAddress = 0x02380000; - newRom2.Header.SubEntryAddress = 0x02380000; - } - byte[] newRomFixed = newRom2.Write(true); - { - uint arm9offset = (uint)(newRomFixed[0x20] | (newRomFixed[0x21] << 8) | (newRomFixed[0x22] << 16) | (newRomFixed[0x23] << 24)); - uint arm9loadaddr = (uint)(newRomFixed[0x28] | (newRomFixed[0x29] << 8) | (newRomFixed[0x2A] << 16) | (newRomFixed[0x2B] << 24)); - uint arm9size = (uint)(newRomFixed[0x2C] | (newRomFixed[0x2D] << 8) | (newRomFixed[0x2E] << 16) | (newRomFixed[0x2F] << 24)); - uint arm7offset = (uint)(newRomFixed[0x30] | (newRomFixed[0x31] << 8) | (newRomFixed[0x32] << 16) | (newRomFixed[0x33] << 24)); - - //arm9 offset becomes 0x180 - newRomFixed[0x20] = 0x80; - newRomFixed[0x21] = 0x01; - newRomFixed[0x22] = 0x00; - newRomFixed[0x23] = 0x00; - //arm9 load becomes 0x02332C40 (rsa_GetDecodedHash) - newRomFixed[0x28] = 0x40; - newRomFixed[0x29] = 0x2C; - newRomFixed[0x2A] = 0x33; - newRomFixed[0x2B] = 0x02; - //arm9 size becomes 0x100 - newRomFixed[0x2C] = 0x00; - newRomFixed[0x2D] = 0x01; - newRomFixed[0x2E] = 0x00; - newRomFixed[0x2F] = 0x00; - ushort newcrc = CRC16.GetCRC16(newRomFixed, 0, 0x15E); - newRomFixed[0x15E] = (byte)(newcrc & 0xFF); - newRomFixed[0x15F] = (byte)(newcrc >> 8); - - exploitData[0x3C] = (byte)(arm7offset & 0xFF); - exploitData[0x3D] = (byte)((arm7offset >> 8) & 0xFF); - exploitData[0x3E] = (byte)((arm7offset >> 16) & 0xFF); - exploitData[0x3F] = (byte)((arm7offset >> 24) & 0xFF); - - exploitData[0x40] = (byte)(arm9offset & 0xFF); - exploitData[0x41] = (byte)((arm9offset >> 8) & 0xFF); - exploitData[0x42] = (byte)((arm9offset >> 16) & 0xFF); - exploitData[0x43] = (byte)((arm9offset >> 24) & 0xFF); - - exploitData[0x44] = (byte)(arm9loadaddr & 0xFF); - exploitData[0x45] = (byte)((arm9loadaddr >> 8) & 0xFF); - exploitData[0x46] = (byte)((arm9loadaddr >> 16) & 0xFF); - exploitData[0x47] = (byte)((arm9loadaddr >> 24) & 0xFF); - - exploitData[0x48] = (byte)(arm9size & 0xFF); - exploitData[0x49] = (byte)((arm9size >> 8) & 0xFF); - exploitData[0x4A] = (byte)((arm9size >> 16) & 0xFF); - exploitData[0x4B] = (byte)((arm9size >> 24) & 0xFF); - - Array.Copy(exploitData, 0, newRomFixed, 0x180, exploitData.Length); - } - SFSDirectory d = fs.GetDirectoryByPath("//ds_demo"); - d.Files.Add(new SFSFile(-1, "rom1.nds", d) { Data = newRomFixed }); - //this is shitty... - d.Files.Remove(d.GetFileByPath("ds_demo/ANDEdemo")); - d.Files.Remove(d.GetFileByPath("ds_demo/AGFEdemo")); - d.Files.Remove(d.GetFileByPath("ds_demo/AMFEclip")); - d.Files.Remove(d.GetFileByPath("ds_demo/AMTEdemo")); - d.Files.Remove(d.GetFileByPath("ds_demo/APTEdemo")); - d.Files.Remove(d.GetFileByPath("ds_demo/ATTEdemo")); - d.Files.Remove(d.GetFileByPath("ds_demo/ATTEpush")); - d.Files.Remove(d.GetFileByPath("ds_demo/testcode")); - d.Files.Remove(d.GetFileByPath("ds_demo/AMCEdemo")); - DemoMenu menu = new DemoMenu(); - menu.entries = new DemoMenu.DemoMenuEntry[] - { - new DemoMenu.DemoMenuEntry() - { - rating = 1, - guideMode = 0x15, - touchText1 = "HaxxStation by Gericom,", - touchText2 = "shutterbug2000, Apache Thunder", - internalName = "rom1.nds" - }, - new DemoMenu.DemoMenuEntry() - { - bannerImage = new byte[512], - bannerPalette = new byte[32], - bannerText1 = "", - bannerText2 = "", - rating = 1, - guideMode = 0x15, - touchText1 = "HaxxStation by Gericom,", - touchText2 = "shutterbug2000, Apache Thunder", - internalName = "rom1.nds" - }, - new DemoMenu.DemoMenuEntry() - { - bannerImage = new byte[512], - bannerPalette = new byte[32], - bannerText1 = "", - bannerText2 = "", - rating = 1, - guideMode = 0x15, - touchText1 = "HaxxStation by Gericom,", - touchText2 = "shutterbug2000, Apache Thunder", - internalName = "rom1.nds" - } - }; - if (newRom2.Banner != null) - { - string[] lines = newRom2.Banner.Banner.GameName[1].Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); - if (lines.Length > 0) - menu.entries[0].bannerText1 = lines[0]; - else - menu.entries[0].bannerText1 = "Bannerless Homebrew"; - if (lines.Length > 1) - menu.entries[0].bannerText2 = lines[1]; - else - menu.entries[0].bannerText2 = ""; - menu.entries[0].bannerImage = newRom2.Banner.Banner.Image; - menu.entries[0].bannerPalette = newRom2.Banner.Banner.Pltt; - } - else - { - menu.entries[0].bannerText1 = "Bannerless Homebrew"; - menu.entries[0].bannerText2 = ""; - menu.entries[0].bannerImage = new byte[512]; - menu.entries[0].bannerPalette = new byte[32]; - } - byte[] demoMenu = menu.Write(); - fs.GetFileByPath("//ds_demo/demomenu").Data = demoMenu; - fs.GetFileByPath("//mb/server").Data = haxxStationServer; - fs.GetFileByPath("//mb/icon.nbfc").Data = haxxStationIconImage; - fs.GetFileByPath("//mb/icon.nbfp").Data = haxxStationIconPltt; - downloadStation.FromFileSystem(fs); - //change banner - downloadStation.Banner.Banner.Image = haxxStationIconImage; - downloadStation.Banner.Banner.Pltt = haxxStationIconPltt; - for(int i = 0; i < 6; i++) - downloadStation.Banner.Banner.GameName[i] = "HaxxStation\nBy Gericom, shutterbug2000\nand Apache Thunder"; - byte[] finalResult = downloadStation.Write(); - File.Create(args[2]).Close(); - File.WriteAllBytes(args[2], finalResult); + PrintUsage(); + return; } + + string dsPath = null; + string outPath = null; + List romPaths = new List(); + string filePath; + //parse arguments + int q = 0; + while (q < args.Length - 1) + { + string arg = args[q++]; + switch (arg) + { + case "-s": + filePath = args[q++]; + if (!File.Exists(filePath)) + { + Console.WriteLine("Error: File (" + filePath + ") does not exist!"); + return; + } + dsPath = filePath; + break; + case "-o": + outPath = args[q++]; + break; + case "-i": + filePath = args[q++]; + if (!File.Exists(filePath)) + { + Console.WriteLine("Error: File (" + filePath + ") does not exist!"); + return; + } + romPaths.Add(filePath); + break; + case "-I": + string dirPath = args[q++]; + if (!Directory.Exists(dirPath)) + { + Console.WriteLine("Error: Directory (" + dirPath + ") does not exist!"); + return; + } + romPaths.AddRange(Directory.GetFiles(dirPath, "*.nds")); + romPaths.AddRange(Directory.GetFiles(dirPath, "*.srl")); + break; + default: + Console.WriteLine("Error: Invalid argument (" + arg + ")\n"); + PrintUsage(); + return; + } + } + + if (dsPath == null) + { + Console.WriteLine("Error: Specify a download station rom!\n"); + PrintUsage(); + return; + } + if (outPath == null) + { + Console.WriteLine("Error: Specify a destination path!\n"); + PrintUsage(); + return; + } + if (romPaths.Count == 0) + { + Console.WriteLine("Error: Specify at least 1 rom!\n"); + PrintUsage(); + return; + } + + byte[] dsdata = File.ReadAllBytes(dsPath); + byte[] sha1 = SHA1.Create().ComputeHash(dsdata); + for (int i = 0; i < 20; i++) + { + if (sha1[i] != dsHash[i]) + { + Console.WriteLine("Error: Invalid download station rom!"); + Console.WriteLine("The patcher is only compatible with:"); + Console.WriteLine("xxxx - DS Download Station - Volume 1 (Kiosk WiFi Demo Cart) (U)(Independent).nds"); + Console.WriteLine("SHA1: F18B55F3E1259C03E10D0ECB549693B42905CEB5"); + return; + } + } + DownloadStationPatcher p = new DownloadStationPatcher(new NDS(dsdata)); + foreach(var r in romPaths) + p.AddRom(new NDS(File.ReadAllBytes(r))); + byte[] finalResult = p.ProduceRom().Write(); + File.Create(outPath).Close(); + File.WriteAllBytes(outPath, finalResult); } } } diff --git a/dspatch/dspatch.csproj b/dspatch/dspatch.csproj index 5ac8735..8eb9a14 100644 --- a/dspatch/dspatch.csproj +++ b/dspatch/dspatch.csproj @@ -44,6 +44,7 @@ +