예제 #1
0
        static FileIDResult Test_UNIF(IdentifyJob job)
        {
            if (!CheckMagic(job.Stream, SimpleMagics.UNIF))
            {
                return(new FileIDResult());
            }

            //TODO - simple parser (for starters, check for a known chunk being next, see http://wiki.nesdev.com/w/index.php/UNIF)

            var ret = new FileIDResult(FileIDType.UNIF, 100);

            return(ret);
        }
예제 #2
0
        static FileIDResult Test_Simple(IdentifyJob job, FileIDType type, SimpleMagicRecord magic)
        {
            var ret = new FileIDResult(type);

            if (CheckMagic(job.Stream, magic))
            {
                return(new FileIDResult(type, 100));
            }
            else
            {
                return(new FileIDResult());
            }
        }
예제 #3
0
        static FileIDResult Test_INES(IdentifyJob job)
        {
            if (!CheckMagic(job.Stream, SimpleMagics.INES))
            {
                return(new FileIDResult());
            }

            var ret = new FileIDResult(FileIDType.INES, 100);

            //an INES file should be a multiple of 8k, with the 16 byte header.
            //if it isnt.. this is fishy.
            if (((job.Stream.Length - 16) & (8 * 1024 - 1)) != 0)
            {
                ret.Confidence = 50;
            }

            return(ret);
        }
예제 #4
0
        static FileIDResult Test_N64(IdentifyJob job)
        {
            //  .Z64 = No swapping
            //  .N64 = Word Swapped
            //  .V64 = Byte Swapped

            //not sure how to check for these yet...
            var ret = new FileIDResult(FileIDType.N64, 5);

            if (job.Extension == "V64")
            {
                ret.ExtraInfo["byteswap"] = true;
            }
            if (job.Extension == "N64")
            {
                ret.ExtraInfo["wordswap"] = true;
            }
            return(ret);
        }
예제 #5
0
        static FileIDResult Test_GB_GBC(IdentifyJob job)
        {
            if (!CheckMagic(job.Stream, SimpleMagics.GB))
            {
                return(new FileIDResult());
            }

            var ret  = new FileIDResult(FileIDType.GB, 100);
            int type = ReadByte(job.Stream, 0x143);

            if ((type & 0x80) != 0)
            {
                ret.FileIDType = FileIDType.GBC;
            }

            //could check cart type and rom size for extra info if necessary

            return(ret);
        }
예제 #6
0
        static FileIDResult Test_BIN_ISO(IdentifyJob job)
        {
            //ok, this is complicated.
            //there are lots of mislabeled bins/isos so lets just treat them the same (mostly)
            //if the BIN cant be recognized, but it is small, it is more likely some other rom BIN than a disc (turbocd or other)

            if (job.Extension == "BIN")
            {
                //first we can check for SMD magic words.
                //since this extension is ambiguous, we can't be completely sure about it. but it's almost surely accurate
                if (CheckMagic(job.Stream, SimpleMagics.SEGAGENESIS))
                {
                    var ret = new FileIDResult(FileIDType.SMD, 95);
                    ret.ExtraInfo["type"] = "genesis";
                    return(ret);
                }

                if (CheckMagic(job.Stream, SimpleMagics.SEGAMEGADRIVE))
                {
                    var ret = new FileIDResult(FileIDType.SMD, 95);
                    ret.ExtraInfo["type"] = "megadrive";
                }
            }

            //well... guess it's a disc.
            //since it's just a bin, we dont need the user to provide a DiscSystem disc.
            //lets just analyze this as best we can.
            //of course, it's a lot of redundant logic with the discsystem disc checker.
            //but you kind of need different approaches when loading a hugely unstructured bin file
            //discsystem won't really even be happy mounting a .bin anyway, and we don't want it to be

            //for PSX, we have a magic word to look for.
            //it's at 0x24E0 with a mode2 (2352 byte) track 1.
            //what if its 2048 byte?
            //i found a ".iso" which was actually 2352 byte sectors..
            //found a hilarious ".bin.iso" which was actually 2352 byte sectors
            //so, I think it's possible that every valid PSX disc is mode2 in the track 1
            if (CheckMagic(job.Stream, SimpleMagics.PSX))
            {
                var ret = new FileIDResult(FileIDType.PSX, 95);
                //this is an unreliable way to get a PSX game!
                ret.ExtraInfo["unreliable"] = true;
                return(ret);
            }

            //it's not proven that this is reliable. this is actually part of the Mode 1 CDFS header. perhaps it's mobile?
            //if it's mobile, we'll need to mount it as an ISO file here via discsystem
            if (CheckMagic(job.Stream, SimpleMagics.PSP))
            {
                return(new FileIDResult(FileIDType.PSP, 95));
            }

            //if this was an ISO, we might discover the magic word at offset 0...
            //if it was a mode2/2352 bin, we might discover it at offset 16 (after the data sector header)
            if (CheckMagic(job.Stream, SimpleMagics.SEGASATURN, 0))
            {
                return(new FileIDResult(FileIDType.Saturn, job.Extension == "ISO" ? 95 : 90));
            }
            if (CheckMagic(job.Stream, SimpleMagics.SEGASATURN, 16))
            {
                return(new FileIDResult(FileIDType.Saturn, job.Extension == "BIN" ? 95 : 90));
            }
            if (CheckMagic(job.Stream, SimpleMagics.SEGADISCSYSTEM, 0))
            {
                return(new FileIDResult(FileIDType.MegaCD, job.Extension == "ISO" ? 95 : 90));
            }
            if (CheckMagic(job.Stream, SimpleMagics.SEGADISCSYSTEM, 16))
            {
                return(new FileIDResult(FileIDType.MegaCD, job.Extension == "BIN" ? 95 : 90));
            }

            if (job.Extension == "ISO")
            {
                return(new FileIDResult(FileIDType.Disc, 1));
            }
            else
            {
                return(new FileIDResult(FileIDType.Multiple, 1));
            }
        }
예제 #7
0
        /// <summary>
        /// performs wise heuristics to identify a file.
        /// this will attempt to return early if a confident result can be produced.
        /// </summary>
        public FileIDResults Identify(IdentifyParams p)
        {
            IdentifyJob job = new IdentifyJob()
            {
                Stream = p.SeekableStream,
                Disc   = p.Disc
            };

            //if we have a disc, that's a separate codepath
            if (job.Disc != null)
            {
                return(IdentifyDisc(job));
            }

            FileIDResults ret = new FileIDResults();

            string ext = p.Extension;

            if (ext != null)
            {
                ext           = ext.TrimStart('.').ToUpper();
                job.Extension = ext;
            }

            if (job.Extension == "CUE")
            {
                ret.ShouldTryDisc = true;
                return(ret);
            }

            if (job.Extension != null)
            {
                //first test everything associated with this extension
                ExtensionInfo handler = null;
                if (ExtensionHandlers.TryGetValue(ext, out handler))
                {
                    foreach (var del in handler.Testers)
                    {
                        var fidr = del(job);
                        if (fidr.FileIDType == FileIDType.None)
                        {
                            continue;
                        }
                        ret.Add(fidr);
                    }

                    ret.Sort();

                    //add a low confidence result just based on extension, if it doesnt exist
                    if (ret.Find((x) => x.FileIDType == handler.DefaultForExtension) == null)
                    {
                        var fidr = new FileIDResult(handler.DefaultForExtension, 5);
                        ret.Add(fidr);
                    }
                }
            }

            ret.Sort();

            //if we didnt find anything high confidence, try all the testers (TODO)

            return(ret);
        }