Example #1
0
        private void infoButton_Click(object sender, EventArgs e)
        {
            var selectedNode = treeView.SelectedNode;

            if (selectedNode == null)
            {
                //Should I display a dialog box? Ehh.... nah (until someone convinces me otherwise)
                return;
            }
            if (!(selectedNode.Tag is FilesystemNode))
            {
                MessageBox.Show("This shouldn't happen and is a sign of programmer error! Tag is not FilesystemNode, it is " + (selectedNode.Tag == null ? "null" : selectedNode.Tag.GetType().FullName));
                return;
            }
            var  selectedFSNode = (FilesystemNode)selectedNode.Tag;
            bool isFile         = selectedFSNode is FilesystemFile;

            var text = new StringBuilder();

            text.AppendFormat("Name: {0}", selectedFSNode.name).AppendLine();
            text.AppendFormat("Type: {0}", isFile ? "File" : "Folder").AppendLine();
            if (isFile)
            {
                var selectedFile = (FilesystemFile)selectedFSNode;
                text.AppendFormat("Offset: 0x{0:X2}", selectedFile.offset).AppendLine();
                text.AppendFormat("Size: {0}", ROMInfo.formatByteSize(selectedFile.size)).AppendLine();
            }
            MessageBox.Show(text.ToString());
        }
Example #2
0
        public static void parseBAMArea(ROMInfo info, WrappedInputStream s, long offset)
        {
            s.Position = offset;

            int firstTrack  = s.read();
            int firstSector = s.read();

            info.addInfo("First directory track", firstTrack);
            info.addInfo("First directory sector", firstSector);

            int diskType = s.read();

            info.addInfo("Disk type", diskType);

            int unused = s.read();

            info.addInfo("Unused", unused, true);

            //TODO Individual BAM entries

            s.Position = offset + 0x90;
            //Official documentation says it goes up to 16 bytes, and the rest are 2-byte 0xa0 padding, 2-byte disk ID, 1 byte unused 0xa0, and "2A" for DOS type. Howevevr, that seems to not actually be the case half the time, as people just put whatever they want here, especially cracking groups
            string diskLabel = Encoding.ASCII.GetString(s.read(27).Select(b => b == 0xa0 ? (byte)0x20 : b).ToArray()).TrimEnd(' ');

            info.addInfo("Internal name", diskLabel);
        }
Example #3
0
 public override void addROMInfo(ROMInfo info, ROMFile file)
 {
     if ("bin".Equals(file.extension) || "rom".Equals(file.extension) || "car".Equals(file.extension))
     {
         byte[] magic = file.stream.read(4);
         if (isCARTMagic(magic))
         {
             info.addInfo("Detected format", "CART header");
             parseCART(info, file.stream);
         }
         else
         {
             //Well, nothing we can really do here, then
             info.addInfo("Platform", "Atari 8-bit");
             info.addInfo("Detected format", "Unheadered");
         }
     }
     else if ("atr".Equals(file.extension))
     {
         addATRInfo(info, file);
     }
     else
     {
         //TODO: Floppy images
         info.addInfo("Platform", "Atari 8-bit");
     }
 }
Example #4
0
        public static void parseCCS64Cart(ROMInfo info, WrappedInputStream s)
        {
            s.Position = 0x10;
            int headerLength = s.readIntBE();

            info.addInfo("Header size", headerLength);

            short version = s.readShortBE();

            info.addInfo("Version", version);             //Is this actually the kind of version I'm thinking of, or is it more like the header version?

            short cartType = s.readShortBE();

            info.addInfo("Type", cartType, CARTRIDGE_TYPES);
            info.addInfo("Platform", cartType == 15 ? "Commodore 64GS" : "Commodore 64");

            int exromLineStatus = s.read();

            info.addInfo("EXROM line status", exromLineStatus == 0 ? "Active" : "Inactive");

            int gameLineStatus = s.read();

            info.addInfo("Game line status", gameLineStatus == 0 ? "Active" : "Inactive");

            byte[] reserved = s.read(6);
            info.addInfo("Reserved", reserved, true);

            string name = s.read(32, Encoding.ASCII).TrimEnd('\0');

            info.addInfo("Internal name", name);
            //TODO Read CHIP packets (not entirely trivial as there can be more than one)
        }
Example #5
0
        public static void parseAttributeFlags(ROMInfo info, int flags)
        {
            //Looks like this is used for PS Vita and PS3 as well whoops
            //1 << 13 is unknown, has something to do with PS Now beta
            //1 << 14, 1 << 15 are unused
            //1 << 18 is unknown
            //1 << 24 and up have something to do with PC Engine but are unknown
            info.addInfo("Remote play v1", (flags & 1 << 0) > 0, true);
            info.addInfo("Copyable", (flags & 1 << 1) > 0, true);
            info.addInfo("Remote play v2", (flags & 1 << 2) > 0, true);
            info.addInfo("XMB In-game forced enabled", (flags & 1 << 3) > 0, true);
            info.addInfo("XMB In-game disabled", (flags & 1 << 4) > 0, true);
            info.addInfo("XMB In-game custom music enabled", (flags & 1 << 5) > 0, true);
            info.addInfo("Voice chat", (flags & 1 << 6) > 0, true);
            info.addInfo("PS Vita remote play", (flags & 1 << 7) > 0, true);

            //Are these actually used on PSP?
            info.addInfo("Move Controller warning", (flags & 1 << 8) > 0, true);
            info.addInfo("Navigation Controller warning", (flags & 1 << 9) > 0, true);
            info.addInfo("PlayStation Eye Cam warning", (flags & 1 << 10) > 0, true);
            info.addInfo("Move Controller needs calibration notification", (flags & 1 << 11) > 0, true);
            info.addInfo("Stereoscopic 3D warning", (flags & 1 << 12) > 0, true);

            //Yeah these don't sound right
            info.addInfo("Install disc", (flags & 1 << 16) > 0, true);
            info.addInfo("Install packages", (flags & 1 << 17) > 0, true);
            info.addInfo("Game purchase enabled", (flags & 1 << 19) > 0, true);
            info.addInfo("Disable About this Game", (flags & 1 << 20) > 0, true);
            info.addInfo("PC Engine", (flags & 1 << 21) > 0, true);
            info.addInfo("License disabled", (flags & 1 << 22) > 0, true);
            info.addInfo("Move controller enabled", (flags & 1 << 23) > 0, true);
        }
Example #6
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            info.addInfo("Platform", "Atari 5200");
            var s = file.stream;

            s.Position = file.length - 3;

            bool skipLogo = s.read() == 0xff;             //Frogger does this, maybe some others. I guess this is the second digit of the year being set to 0xff?

            info.addInfo("Skip BIOS", skipLogo);
            short entryPoint = s.readShortLE();

            info.addInfo("Entry point", entryPoint, ROMInfo.FormatMode.HEX);

            if (!skipLogo)
            {
                s.Position = file.length - 24;
                //Copyright info is usually displayed on the screen, the BIOS displays a graphic from its own ROM and something like "TITLE\nCOPYRIGHT YEAR ATARI"
                //This can be used to get the name for our purposes, though it will be padded with @ (displays as blank I guess?) or null char to make it centred on screen
                string name = decodeAtari5200String(s.read(20));
                info.addInfo("Internal name", name);

                int yearFirstDigit  = s.read() - 0x50;
                int yearSecondDigit = s.read() - 0x50;

                //Nice Y2K bug m8
                info.addInfo("Year", 1900 + (yearFirstDigit * 10) + yearSecondDigit);
            }

            //TODO: BIOS disassemby also mentions something about PAL carts? I wasn't aware of any PAL carts or even PAL 5200 systems, so that's interesting if that actually exists; it seems that PAL carts have something different at xFE7
        }
Example #7
0
        protected override void ReadInfo(string filename)
        {
            base.ReadInfo(filename);
            long sum = 0;

            for (int i = 0; i < SectionHeader.Length; i++)
            {
                sum += CRC[i];
                if (SectionHeader[i].sh_offset != 0 &&
                    SectionHeader[i].sh_addr == 0x10000000 &&
                    SectionName[i] == ".rodata")
                {
                    FileStream fs          = File.Open(filename, FileMode.Open);
                    byte[]     sectionData = new byte[SectionHeader[i].sh_size];
                    fs.Position = SectionHeader[i].sh_offset;
                    fs.Read(sectionData, 0, sectionData.Length);
                    fs.Close();

                    if ((SectionHeader[i].sh_flags & (uint)SHF_RPL.ZLIB) == (uint)SHF_RPL.ZLIB)
                    {
                        sectionData = Decompress(sectionData);
                    }

                    ROM = new ROMInfo(sectionData);
                }
            }
            sum    -= (long)CRC[2] + CRC[3] + CRC[CRC.Length - 1];
            CRCsSum = (uint)(sum >> 4);
        }
Example #8
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            //FIXME: Damn nothing matters anymore just refactor everything on the planet

            //.iso files are 2048 sectors, and since they're read as normal ROM files without any special handling in ROMScanner, we'll specify that sector size here; for cue sheets we've already read that so we just do the thing
            int sectorSize = 2048;

            if (file.cdSectorSize != 0)
            {
                sectorSize = file.cdSectorSize;
            }
            if (file.extension.Equals("img"))
            {
                sectorSize = 2352;
            }

            info.addInfo("Sector size", sectorSize);

            if (sectorSize == 2352)
            {
                addROMInfo(info, file, new CDInputStream(file.stream));
            }
            else
            {
                addROMInfo(info, file, file.stream);
            }
        }
Example #9
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            info.addInfo("Platform", "Nintendo 64");

            WrappedInputStream s = file.stream;

            byte[]       header = s.read(4);
            N64ROMFormat format = detectFormat(header);

            info.addInfo("Detected format", detectFormat(header));

            if (!isDiskFormat(format) && isDiskExtension(file.extension))
            {
                //Some kind of 64DD disk with an unknown format (might be a dev disk or something, or a bad dump with no system area)
                return;
            }
            else if (isDiskFormat(format))
            {
                parse64DDDiskInfo(info, s);
            }
            else if (format == N64ROMFormat.V64)
            {
                ByteSwappedInputStream swappedInputStream = new ByteSwappedInputStream(s);
                parseN64ROM(swappedInputStream, info);
            }
            else
            {
                parseN64ROM(s, info);
            }
            //Haha I'm sure word swapping will be a lot of fun
        }
Example #10
0
        public static void parseRatings(ROMInfo info, byte[] ratings, bool isDSi)
        {
            //Used with Wii/WiiWare and DSi, which both introduced parental controls features I guess
            //DSi seems to use bit 7 to indicate if a rating exists for a given country differently
            //To be precise: With DSi (and 3DS), bit 7 is set when a rating exists, on Wii, bit 7 is unset when a rating exists
            //Wii U has ratings too, but they're XML. Seemingly very similar, though


            for (int i = 0; i < 16; ++i)
            {
                int    rating = ratings[i];
                string ratingName;
                if (i >= RATING_NAMES.Length)
                {
                    ratingName = "Unknown rating " + (i - RATING_NAMES.Length);
                }
                else
                {
                    ratingName = RATING_NAMES[i].Item1 + " rating";
                }

                IDictionary <int, string> ratingsDict = null;
                if (i < RATING_NAMES.Length && RATING_NAMES[i].Item2 != null)
                {
                    ratingsDict = RATING_NAMES[i].Item2;
                }
                parseRating(info, rating, ratingName, ratingsDict, isDSi);
            }
        }
Example #11
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            if ("dol".Equals(file.extension))
            {
                //TODO Parse what little info there is out of dol (could use this for boot .dol and Wii homebrew .dol too I guess)
                info.addInfo("Platform", "GameCube");
                return;
            }

            WrappedInputStream s = file.stream;

            byte[] magic = s.read(4);
            if (isTGCMagic(magic))
            {
                s.Position = 8;
                int tgcHeaderSize = s.readIntBE();
                info.addInfo("TGC header size", tgcHeaderSize, ROMInfo.FormatMode.SIZE);

                //What the f**k? What does Dolphin know that YAGD doesn't and didn't decide to tell the rest of the class?
                s.Position = 0x24;
                int realOffset = s.readIntBE();
                s.Position = 0x34;
                int virtualOffset = s.readIntBE();
                int fileOffset    = realOffset - virtualOffset;
                parseGamecubeDisc(info, s, tgcHeaderSize, fileOffset, true);
            }
            else
            {
                parseGamecubeDisc(info, s, 0, 0, false);
            }
        }
Example #12
0
 public override void addROMInfo(ROMInfo info, ROMFile file)
 {
     if ("bin".Equals(file.extension))
     {
         parseAPFCart(info, file.stream);
     }
 }
Example #13
0
        public static void parseT64(ROMInfo info, WrappedInputStream s)
        {
            info.addInfo("Platform", "Commodore 64");
            s.Position = 32;

            short version = s.readShortLE();

            info.addInfo("Version", version);

            short dirEntries = s.readShortLE();

            info.addInfo("Number of files", dirEntries);

            short usedEntries = s.readShortLE();

            info.addInfo("Number of used entries", usedEntries);

            short reserved = s.readShortLE();

            info.addInfo("Reserved", reserved, true);

            string name = s.read(24, Encoding.ASCII).TrimEnd(' ');

            info.addInfo("Internal name", name);
        }
Example #14
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            WrappedInputStream s = file.stream;

            string copyrightInfo = s.read(28, Encoding.ASCII);

            info.addInfo("Copyright", copyrightInfo, true);
            //For first party games this should say that, and for third party games it should say " LICENSED BY SNK CORPORATION"
            info.addInfo("First party", "COPYRIGHT BY SNK CORPORATION".Equals(copyrightInfo));

            byte[] entryPoint = s.read(4);
            info.addInfo("Entry point", entryPoint, ROMInfo.FormatMode.HEX, true);

            short gameNumber = s.readShortLE();

            info.addInfo("Product code", gameNumber.ToString("X2"));

            int version = s.read();

            info.addInfo("Version", version);

            bool isColor = s.read() == 0x10;

            info.addInfo("Is colour", isColor);
            info.addInfo("Platform", isColor ? "Neo Geo Pocket Color" : "Neo Geo Pocket");


            string internalName = s.read(12, Encoding.ASCII);

            info.addInfo("Internal name", internalName);

            byte[] reserved = s.read(16);
            info.addInfo("Reserved", reserved, true);             //Should be 0 filled
        }
Example #15
0
        public static void addSupercardDS2PluginInfo(ROMInfo info, ROMFile file)
        {
            info.addInfo("Platform", "Supercard DSTwo");
            string iconFilename = System.IO.Path.ChangeExtension(file.name, "bmp");
            //The icon is actually pointed to in the .ini file, but it's in a native DS format (starts with fat1:/) so it won't be of any use unless running on an actual DSTwo. Luckily, the filename is always the same as the .plg but with a .bmp extension; and this is the kind of convention that nobody would dare break
            var icon = Image.FromStream(file.getSiblingFile(iconFilename));

            info.addInfo("Icon", icon);

            string iniFilename = System.IO.Path.ChangeExtension(file.name, "ini");

            using (var sr = new System.IO.StreamReader(file.getSiblingFile(iniFilename))) {
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    if (line == null)
                    {
                        break;
                    }

                    if (line.ToLowerInvariant().StartsWith("name="))
                    {
                        //Once again, not really internal. I kinda want to rename this column globally, it's already kinda wordy and a mouthful and I don't like that
                        info.addInfo("Internal name", line.Split('=')[1]);
                        break;
                    }
                }
            }
        }
Example #16
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            info.addInfo("Platform", name);
            WrappedInputStream s = file.stream;

            s.Seek(-544, System.IO.SeekOrigin.End);             //Yeah, this one's a bit weird

            string title = s.read(20, MainProgram.shiftJIS).TrimEnd(' ');

            info.addInfo("Internal name", title);
            byte[] reserved = s.read(5);
            info.addInfo("Reserved", reserved, true);
            string makerCode = s.read(2, Encoding.ASCII);

            info.addInfo("Publisher", makerCode, NintendoCommon.LICENSEE_CODES);
            string productCode = s.read(4, Encoding.ASCII);

            info.addInfo("Product code", productCode);
            //I don't know what to do about the game type, since it's all V so far
            info.addInfo("Type", productCode[0], true);
            string shortTitle = productCode.Substring(1, 2);

            info.addInfo("Short title", shortTitle);
            char country = productCode[3];

            info.addInfo("Country", country, NintendoCommon.COUNTRIES);
            int version = s.read();

            info.addInfo("Version", version);
        }
Example #17
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            info.addInfo("Platform", name);

            var s = file.stream;

            s.Position = 0x100;
            byte[] magic = s.read(4);
            if (isNCSDMagic(magic))
            {
                info.addInfo("Detected format", "NCSD");
                parseNCSD(info, file, true);
            }
            else if (isNCCHMagic(magic))
            {
                info.addInfo("Detected format", "NCCH");
                parseNCCH(info, file.stream, null);
            }
            else
            {
                s.Position = 0;
                magic      = s.read(4);
                if (is3DSXMagic(magic))
                {
                    info.addInfo("Detected format", "3DSX");
                    parse3DSX(info, file);
                }
            }
            //TODO CIA https://www.3dbrew.org/wiki/CIA
        }
Example #18
0
        public static void parsePlainRegion(ROMInfo info, WrappedInputStream s, string prefix, long offset = 0)
        {
            s.Position = offset;

            //TODO: Only read up to plainRegionSize bytes
            List <string> libs = new List <string>();

            while (true)
            {
                int c = s.read();
                if (c == -1 | c == 0)
                {
                    break;
                }

                StringBuilder sb = new StringBuilder();
                sb.Append((char)c);
                while (true)
                {
                    int cc = s.read();
                    if (cc == -1 | cc == 0)
                    {
                        break;
                    }
                    sb.Append((char)cc);
                }
                libs.Add(sb.ToString());
            }
            info.addInfo(combinePrefix(prefix, "Libraries used"), String.Join(", ", libs));
        }
Example #19
0
        public static void parsePeripheralInfo(ROMInfo info, int peripherals)
        {
            info.addInfo("Uses Windows CE?", (peripherals & (1 << 0)) > 0);
            info.addInfo("Supports VGA box?", (peripherals & (1 << 4)) > 0);
            info.addInfo("Supports other expansions", (peripherals & (1 << 8)) > 0);   //Well that's just mysterious, thanks
            info.addInfo("Supports rumble", (peripherals & (1 << 9)) > 0);             //The "Dreamcast Jump Pack"/"Vibration Pack"/"Puru Puru Pack" accessory
            info.addInfo("Supports microphone", (peripherals & (1 << 10)) > 0);
            info.addInfo("Supports memory card", (peripherals & (1 << 11)) > 0);
            info.addInfo("Requires Start + A + B + dpad", (peripherals & (1 << 12)) > 0);
            info.addInfo("Requires C button", (peripherals & (1 << 13)) > 0);
            info.addInfo("Requires D button", (peripherals & (1 << 14)) > 0);
            info.addInfo("Requires X button", (peripherals & (1 << 15)) > 0);
            info.addInfo("Requires Y button", (peripherals & (1 << 16)) > 0);
            info.addInfo("Requires Z button", (peripherals & (1 << 17)) > 0);
            info.addInfo("Requires expanded dpad", (peripherals & (1 << 18)) > 0);
            info.addInfo("Requires analog R trigger", (peripherals & (1 << 19)) > 0);
            info.addInfo("Requires analog L trigger", (peripherals & (1 << 20)) > 0);
            info.addInfo("Requires analog horizontal", (peripherals & (1 << 21)) > 0);
            info.addInfo("Requires analog vertical", (peripherals & (1 << 22)) > 0);
            info.addInfo("Requires expanded analog horizontal", (peripherals & (1 << 23)) > 0);
            info.addInfo("Requires expanded analog vertical", (peripherals & (1 << 24)) > 0);

            //Hmm... other documentation says "supports gun" but looking at games with this flag set, that's clearly wrong. This works out, though.
            info.addInfo("Supports keyboard", (peripherals & (1 << 25)) > 0);

            //So... what are these? Are there flags for maracas, racing wheel, fishing rod (motion sensing), and actual gun? Is mouse separate?
            //The documentation that says bit 25 == gun says that these are mouse and keyboard respectively, but that seems incorrect, except for in homebrew that believes that documentation; otherwise these might just be unused
            info.addInfo("Supports unknown peripheral 1", (peripherals & (1 << 26)) > 0);
            info.addInfo("Supports unknown peripheral 2", (peripherals & (1 << 27)) > 0);
            info.addInfo("Supports unknown peripheral 3", (peripherals & (1 << 28)) > 0);
            info.addInfo("Supports unknown peripheral 4", (peripherals & (1 << 29)) > 0);
            info.addInfo("Supports unknown peripheral 5", (peripherals & (1 << 30)) > 0);
            info.addInfo("Supports unknown peripheral 6", (peripherals & (1 << 31)) > 0);
        }
Example #20
0
 public override void addROMInfo(ROMInfo info, ROMFile file)
 {
     if ("nro".Equals(file.extension))
     {
         addNROInfo(info, file);
     }
 }
Example #21
0
        private void addArchiveException(object sender, ROMScanner.ExceptionEventArgs args)
        {
            var     row  = new ROMScanner.HaveRowEventArgs();
            ROMInfo info = new ROMInfo();

            row.info = info;

            try {
                info.addInfo("Filename", args.path.Name);
            } catch (Exception ex) {
                info.addInfo("Filename", "Exception: " + ex.ToString());
            }
            try {
                info.addInfo("Folder", args.path.DirectoryName);
            } catch (Exception ex) {
                //F**k you .NET these methods should not throw exceptions at all, let alone because a path dares to be longer than
                //260 characters. No seriously f**k you, that's f*****g stupid, f**k you and your stupid f*****g asinine operating
                //system and its f*****g idiotic limitations. F**k off I am not going to make all my users upgrade to Windows 10 and
                //tweak some group policy just so they can do things. F**k you, things clearly work with a f*****g network drive that
                //has paths that long so clearly Windows works with that shit anyway and you just f****d everything up because you're
                //a f*****g incompetent fuckload of assclowns and I hate you
                info.addInfo("Folder", "Exception: " + ex.ToString());
            }
            info.addInfo("Exception", args.ex);

            addRow(this, row);
        }
Example #22
0
        public static void parseDSiHeader(ROMInfo info, WrappedInputStream s)
        {
            s.Position = 0x1b0;
            int regionFlags = s.readIntLE();

            //There's only 6 bits used, everything else is reserved. What a good use of 5 bytes!
            if (regionFlags == -1)
            {
                //Hmm... Pokemon gen 5 games (I sure do talk about them a lot, huh? Well, they're weird. And they're good games) use 0xffffffef / -17 here, actually; explain that one nerd (bit 27 I guess? But then what the heck)
                info.addInfo("Region", "Region free");
            }
            else
            {
                info.addInfo("Region", Enum.ToObject(typeof(DSiRegionFlags), regionFlags).ToString());
            }

            s.Position = 0x210;
            int usedROMSize = s.readIntLE();

            info.addInfo("Used ROM size", usedROMSize, ROMInfo.FormatMode.SIZE);

            info.addInfo("DSi reserved", s.read(4), true);
            info.addInfo("DSi reserved 2", s.read(4), true);
            info.addInfo("DSi reserved 3", s.read(4), true);

            int modcryptOffset = s.readIntLE();

            info.addInfo("Modcrypt area 1 offset", modcryptOffset, ROMInfo.FormatMode.HEX, true);
            int modcryptSize = s.readIntLE();

            info.addInfo("Modcrypt area 1 size", modcryptSize, ROMInfo.FormatMode.SIZE, true);
            int modcryptOffset2 = s.readIntLE();

            info.addInfo("Modcrypt area 2 offset", modcryptOffset2, ROMInfo.FormatMode.HEX, true);
            int modcryptSize2 = s.readIntLE();

            info.addInfo("Modcrypt area 2 size", modcryptSize2, ROMInfo.FormatMode.SIZE, true);

            string emagCode = s.read(4, Encoding.ASCII);

            info.addInfo("Game code backwards", emagCode, true);
            int dsiType = s.read();

            info.addInfo("Filetype", dsiType, DSI_TYPES);
            byte[] titleIDReserved = s.read(3);             //Usually 00 03 00 for some reason
            info.addInfo("DSi title ID reserved", titleIDReserved, true);

            int publicSaveSize = s.readIntLE();

            info.addInfo("DSiWare public.sav filesize", publicSaveSize, ROMInfo.FormatMode.SIZE);
            int privateSaveSize = s.readIntLE();

            info.addInfo("DSiWare private.sav filesize", publicSaveSize, ROMInfo.FormatMode.SIZE);

            info.addInfo("DSi reserved 4", s.read(176), true);

            byte[] ratings = s.read(16);
            NintendoCommon.parseRatings(info, ratings, true);
        }
Example #23
0
        public static void parseSMSROM(ROMInfo info, ROMFile file)
        {
            WrappedInputStream s = file.stream;

            long headerOffset = -1;

            //Supposedly the header _could_ be at 0x1ff0 or 0x3ff0 but no known software does that. But let's check it anyway just for something to do
            s.Position = 0x1ff0;
            string magic = "TMR SEGA";

            if (s.read(8, Encoding.ASCII).Equals(magic))
            {
                headerOffset = s.Position;
            }
            else
            {
                s.Position = 0x3ff0;
                if (s.read(8, Encoding.ASCII).Equals(magic))
                {
                    headerOffset = s.Position;
                }
                else
                {
                    s.Position = 0x7ff0;
                    if (s.read(8, Encoding.ASCII).Equals(magic))
                    {
                        headerOffset = s.Position;
                    }
                }
            }

            if (headerOffset != -1)
            {
                //It's entirely possible this header isn't there, since Japanese Master Systems don't check for it
                //and therefore Japanese Master System games aren't required to have it
                info.addInfo("Header position", headerOffset, true);
                info.addInfo("Has standard header", true);
                bool isGameGear = "gg".Equals(file.extension);
                parseSegaHeader(info, s, headerOffset, isGameGear);
            }
            else
            {
                info.addInfo("Has standard header", false);
            }

            s.Position = 0x7fe0;
            if (s.read(4, Encoding.ASCII).Equals("SDSC"))
            {
                info.addInfo("Has SDSC header", true);

                parseSDSCHeader(info, s);
            }
            else
            {
                info.addInfo("Has SDSC header", false);
            }

            //TODO Codemasters header (tricky to detect presence, and I don't have any Codemasters games anyway)
        }
Example #24
0
        private void addNROInfo(ROMInfo info, ROMFile file)
        {
            var s = file.stream;

            s.Seek(16, SeekOrigin.Begin);
            var magic = s.read(4, Encoding.ASCII);

            info.addInfo("Magic", magic);
            if (!("NRO0".Equals(magic)))
            {
                return;
            }
            int nroFormatVersion = s.readIntLE();             //Always 0

            info.addInfo("NRO format version", nroFormatVersion, true);
            int totalSize = s.readIntLE();

            info.addInfo("ROM size", totalSize, ROMInfo.FormatMode.SIZE);
            //Skip over flags (unused), segmentHeader[3] (text, ro, data), bssSize, reserved (unused)
            s.Seek(4 + (8 * 3) + 4 + 4, SeekOrigin.Current);
            var buildID = s.read(32);

            info.addInfo("Build ID", buildID);
            info.addInfo("Build ID as ASCII", Encoding.ASCII.GetString(buildID));
            //Skip over reserved 2 and segmentHeader2[3] (apiInfo, dynstr, dynsym)
            //s.Seek(8 + (8 * 3), SeekOrigin.Current);

            s.Seek(totalSize, SeekOrigin.Begin);
            var assetMagic = s.read(4, Encoding.ASCII);

            if ("ASET".Equals(assetMagic))
            {
                long assetSectionStart = s.Position - 4;
                info.addInfo("Asset section offset", assetSectionStart, ROMInfo.FormatMode.HEX);
                int assetFormatVersion = s.readIntLE();
                info.addInfo("Asset format version", assetFormatVersion, true);
                ulong iconOffset = (ulong)(s.readIntLE() | (s.readIntLE() << 4));
                info.addInfo("Icon offset", iconOffset, ROMInfo.FormatMode.HEX);
                ulong iconSize = (ulong)(s.readIntLE() | (s.readIntLE() << 4));
                info.addInfo("Icon size", iconSize, ROMInfo.FormatMode.SIZE);
                ulong nacpOffset = (ulong)(s.readIntLE() | (s.readIntLE() << 4));
                info.addInfo(".nacp offset", nacpOffset, ROMInfo.FormatMode.HEX);
                ulong nacpSize = (ulong)(s.readIntLE() | (s.readIntLE() << 4));
                info.addInfo(".nacp size", nacpSize, ROMInfo.FormatMode.SIZE);
                ulong romfsOffset = (ulong)(s.readIntLE() | (s.readIntLE() << 4));
                info.addInfo("RomFS offset", romfsOffset, ROMInfo.FormatMode.HEX);
                ulong romfsSize = (ulong)(s.readIntLE() | (s.readIntLE() << 4));
                info.addInfo("RomFS size", romfsSize, ROMInfo.FormatMode.SIZE);

                if (iconSize > 0)
                {
                    s.Seek((long)((ulong)assetSectionStart + iconOffset), SeekOrigin.Begin);
                    byte[] icon = s.read((int)iconSize);
                    using (MemoryStream mem = new MemoryStream(icon)) {
                        info.addInfo("Icon", System.Drawing.Image.FromStream(mem));
                    }
                }
            }
        }
Example #25
0
 public override void addROMInfo(ROMInfo info, ROMFile file)
 {
     info.addInfo("Platform", "Xbox");
     if ("xbe".Equals(file.extension))
     {
         parseXBE(info, file.stream);
     }
 }
Example #26
0
 public override void addROMInfo(ROMInfo info, ROMFile file)
 {
     info.addInfo("Platform", "Wii U");
     if ("rpx".Equals(file.extension))
     {
         addRPXInfo(info, file);
     }
 }
Example #27
0
        //It probably uses Latin-1 actually, but this is the closest we can have without potentially breaking things on non-standard .NET platforms

        static void parseBanner(ROMInfo info, byte[] banner, int region)
        {
            string bannerMagic = Encoding.ASCII.GetString(banner, 0, 4);

            info.addInfo("Banner magic", bannerMagic, true);

            info.addInfo("Icon", convertBannerIcon(banner));

            if ("BNR1".Equals(bannerMagic))
            {
                //TODO These variable names f****n suck and this whole thing needs refactoring
                //FIXME: Sonic Adventure DX (Prototype - Review) (hidden-palace.org).gcz is a completely NTSC USA disc with English gameplay and text and audio and whatnot, but has a Japanese banner for some reason. Not sure if I would consider this to be just the disc being weird, or if it's worth fixing, would need to know what it does on real hardware I guess, but anyway it displays mojibake here (and in Dolphin, fwiw) because it's actually using Shift-JIS text that we're decoding as Latin-1 (because disc region is NTSC-U). Can't use Shift-JIS everywhere because then it'd not work with extended ASCII characters (accented letters mostly) on actual NTSC-U discs
                if (region == 0)                   //NTSC-J
                {
                    string title  = MainProgram.shiftJIS.GetString(banner, 0x1820, 32);
                    string title2 = MainProgram.shiftJIS.GetString(banner, 0x1840, 32);
                    info.addInfo("Japanese short title", title + Environment.NewLine + title2);

                    string title3 = MainProgram.shiftJIS.GetString(banner, 0x1860, 64);
                    string title4 = MainProgram.shiftJIS.GetString(banner, 0x18a0, 64);
                    info.addInfo("Japanese title", title3 + Environment.NewLine + title4);

                    string title5 = MainProgram.shiftJIS.GetString(banner, 0x18e0, 128);
                    info.addInfo("Japanese description", title5.Replace("\n", Environment.NewLine));
                }
                else
                {
                    string title  = windows1252.GetString(banner, 0x1820, 32);
                    string title2 = windows1252.GetString(banner, 0x1840, 32);
                    info.addInfo("English short title", title + Environment.NewLine + title2);

                    string title3 = windows1252.GetString(banner, 0x1860, 64);
                    string title4 = windows1252.GetString(banner, 0x18a0, 64);
                    info.addInfo("English title", title3 + Environment.NewLine + title4);

                    string title5 = windows1252.GetString(banner, 0x18e0, 128);
                    info.addInfo("English description", title5.Replace("\n", Environment.NewLine));
                }
            }
            else if ("BNR2".Equals(bannerMagic))
            {
                int baseOffset = 0x1820;

                for (int i = 0; i < 5; ++i)
                {
                    string title  = windows1252.GetString(banner, baseOffset + (i * 320), 32);
                    string title2 = windows1252.GetString(banner, baseOffset + (i * 320) + 32, 32);
                    info.addInfo(languageNames[i] + " short title", title + Environment.NewLine + title2);

                    string title3 = windows1252.GetString(banner, baseOffset + (i * 320) + 64, 64);
                    string title4 = windows1252.GetString(banner, baseOffset + (i * 320) + 128, 64);
                    info.addInfo(languageNames[i] + " title", title3 + Environment.NewLine + title4);

                    string title5 = windows1252.GetString(banner, baseOffset + (i * 320) + 192, 128);
                    info.addInfo(languageNames[i] + " description", title5.Replace("\n", Environment.NewLine));
                }
            }
        }
Example #28
0
 public override void addROMInfo(ROMInfo info, ROMFile file, WrappedInputStream stream)
 {
     Megadrive.parseMegadriveROM(info, stream, true);
     //There's also a "MAIN SEGAOS" at 0x3000 followed by what appears to be some kind of title. Does that mean anything? I don't know
     //Some more info:
     //https://forums.sonicretro.org/index.php?showtopic=30588
     //https://segaretro.org/Sega_CD_programming_FAQ_(1998-12-06)
     //So 0x200 and beyond may have some kind of boot code which could then be checksummed to determine region, perhaps...
 }
Example #29
0
 public override void addROMInfo(ROMInfo info, ROMFile file)
 {
     info.addInfo("Platform", "PlayStation Portable");
     if ("pbp".Equals(file.extension))
     {
         parsePBP(info, file.stream);
     }
     //.iso will be done later
 }
Example #30
0
 static string detectSoundDriver(ROMInfo info, byte[] bytes)
 {
     if (ByteSearch.contains(bytes, MP2K_SELECTSONG))
     {
         //The standard driver among most GBA games, seemingly included in the official GBA SDK (apparently). Otherwise
         //known as Sappy or M4A
         return("MP2000");
     }
     else if (ByteSearch.contains(bytes, MP2K_NEW_SELECTSONG))
     {
         //Apparently it was also recompiled at some point and some games use it (Mother 3, Minish Cap, some others) but there doesn't seem to be any consistency in terms of new games using this and older games using the allegedly older driver
         return("MP2000 (new)");
     }
     else if (ByteSearch.contains(bytes, NATSUME_MAIN))
     {
         //Not sure what uses this. Games developed by Natsume, I guess (which amounts to basically Medabots, Keitai Denju Telefang 2, Buffy the Vampire Slayer, Shaun Palmer's Pro Snowboarder, some Power Rangers and wrestling games)
         return("Natsume");
     }
     else if (ByteSearch.contains(bytes, KRAWALL_MIXCENTER))
     {
         //A third party thing that plays converted s3m/xm files, used by a few games such as
         //Lord of the Rings and The Sims according to the author's website, and also
         //Dora the Explorer: Dora's World Adventure and Harry Potter and the Prisoner of Azkaban (but
         //not the other Dora or Harry Potter games), unless I'm actually detecting this all wrong
         //and they use something else. It's possible I am because it appears in a few homebrew
         //demos (excluding the obvious Krawall Demo), but then maybe they actually do use it since it's now LGPL'd
         //so I guess I should check the credits of those?
         return("Krawall");
     }
     else if (ByteSearch.contains(bytes, RARE_AUDIO_ERROR))
     {
         //Games developed by Rare have this huge block of error text. This is probably the most wrong way to
         //possibly do this but it works and whatnot so maybe it isn't. But I feel dirty for doing this
         return("Rare");
     }
     else if (ByteSearch.contains(bytes, GAX2_INIT))
     {
         //Used by various third-party games. All of them have a block of copyright text
         //specifying that the game uses the GAX engine, and also the version which is nice, that
         //the engine is developed by Shin'en Multimedia, and also some function names like
         //GAX2_INIT a bit after that block. Although I feel like this might result in
         //false positives.... should be fine, hopefully
         return("GAX");
     }
     else if (ByteSearch.contains(bytes, LOGIK_STATE_COPYRIGHT))
     {
         //I don't know what to call this one; used in a few third party games (Asterisk & Obelisk XXL, Driv3r among others)
         //Gotta admit I don't really like this and should detect it better, but it is apparent that those two games use things by this
         //company at least
         return("GBAModPlay/LS_Play");
     }
     else
     {
         return("Unknown");
     }
 }