public void TestByteSwap32()
        {
            var a = new byte[] { 0x67, 0x45, 0x23, 0x01, 0xEF, 0xCD, 0xAB, 0x89 };

            EndiannessUtils.MutatingByteSwap32(a);
            Assert.IsTrue(a.SequenceEqual(expected));
        }
示例#2
0
        /// <exception cref="Exception"><paramref name="file"/> does not exist</exception>
        public RomGame(HawkFile file, string patch)
        {
            if (!file.Exists)
            {
                throw new Exception("The file needs to exist, yo.");
            }

            Extension = file.Extension.ToUpperInvariant();

            var stream     = file.GetStream();
            int fileLength = (int)stream.Length;

            // read the entire contents of the file into memory.
            // unfortunate in the case of large files, but that's what we've got to work with for now.

            // if we're offset exactly 512 bytes from a 1024-byte boundary,
            // assume we have a header of that size. Otherwise, assume it's just all rom.
            // Other 'recognized' header sizes may need to be added.
            int headerOffset = fileLength % BankSize;

            if (headerOffset.In(0, 128, 512) == false)
            {
                Console.WriteLine("ROM was not a multiple of 1024 bytes, and not a recognized header size: {0}. Assume it's purely ROM data.", headerOffset);
                headerOffset = 0;
            }
            else if (headerOffset > 0)
            {
                Console.WriteLine("Assuming header of {0} bytes.", headerOffset);
            }

            // read the entire file into FileData.
            FileData        = new byte[fileLength];
            stream.Position = 0;
            stream.Read(FileData, 0, fileLength);

            // if there was no header offset, RomData is equivalent to FileData
            // (except in cases where the original interleaved file data is necessary.. in that case we'll have problems..
            // but this whole architecture is not going to withstand every peculiarity and be fast as well.
            if (headerOffset == 0)
            {
                RomData = FileData;
            }
            else if (file.Extension == ".dsk" || file.Extension == ".tap" || file.Extension == ".tzx" ||
                     file.Extension == ".pzx" || file.Extension == ".csw" || file.Extension == ".wav" || file.Extension == ".cdt" || file.Extension == ".nsf")            //RTC_Hijack - Add NSF to allowed files
            {
                // these are not roms. unfortunately if treated as such there are certain edge-cases
                // where a header offset is detected. This should mitigate this issue until a cleaner solution is found
                // (-Asnivor)
                RomData = FileData;
            }
            else
            {
                // if there was a header offset, read the whole file into FileData and then copy it into RomData (this is unfortunate, in case RomData isn't needed)
                int romLength = fileLength - headerOffset;
                RomData = new byte[romLength];
                Buffer.BlockCopy(FileData, headerOffset, RomData, 0, romLength);
            }

            if (file.Extension == ".smd")
            {
                RomData = DeInterleaveSMD(RomData);
            }

            if (file.Extension == ".z64" || file.Extension == ".n64" || file.Extension == ".v64")
            {
                // Use a simple magic number to detect N64 rom format, then byteswap the ROM to ensure a consistent endianness/order
                RomData = RomData[0] switch
                {
                    0x37 => EndiannessUtils.ByteSwap16(RomData), // V64 format (byte swapped)
                    0x40 => EndiannessUtils.ByteSwap32(RomData), // N64 format (word swapped)
                    _ => RomData                                 // Z64 format (no swap), or something unexpected; in either case do nothing
                };
            }

            // note: this will be taking several hashes, of a potentially large amount of data.. yikes!
            GameInfo = Database.GetGameInfo(RomData, file.Name);

            if (GameInfo.NotInDatabase && headerOffset == 128 && file.Extension == ".a78")
            {
                // if the game is not in the DB, add the header back in so the core can use it
                // for now only .A78 games, but probably should be for other systems as well
                RomData = FileData;
            }

            CheckForPatchOptions();

            if (patch != null)
            {
                using var patchFile = new HawkFile(patch);
                patchFile.BindFirstOf(".ips");
                if (patchFile.IsBound)
                {
                    RomData = IPS.Patch(RomData, patchFile.GetStream());
                }
            }
        }
示例#3
0
        private static bool IsValidFormatVersion2And3(Stream stream, int entrySize, out bool isBigEndian)
        {
            isBigEndian = false;

            // check stream length
            if (stream.Length <= 4 + entrySize)
            {
                return(false);
            }

            byte[] testData = new byte[4 + entrySize];
            stream.Read(testData, 0, 4 + entrySize);
            stream.Position = 0;

            int numOfFiles = BitConverter.ToInt32(testData, 0);

            // num of files sanity check
            if (numOfFiles > 1024 || numOfFiles < 1 || (numOfFiles * entrySize) > stream.Length)
            {
                numOfFiles = EndiannessUtils.Swap(numOfFiles);

                if (numOfFiles > 1024 || numOfFiles < 1 || (numOfFiles * entrySize) > stream.Length)
                {
                    return(false);
                }

                isBigEndian = true;
            }

            // check if the name field is correct
            bool nameTerminated = false;

            for (int i = 0; i < entrySize - 4; i++)
            {
                if (testData[4 + i] == 0x00)
                {
                    if (i == 0)
                    {
                        return(false);
                    }

                    nameTerminated = true;
                }

                if (testData[4 + i] != 0x00 && nameTerminated)
                {
                    return(false);
                }
            }

            // first entry length sanity check
            int length = BitConverter.ToInt32(testData, entrySize);

            if (length >= stream.Length || length < 0)
            {
                length = EndiannessUtils.Swap(length);

                if (length >= stream.Length || length < 0)
                {
                    return(false);
                }

                isBigEndian = true;
            }

            return(true);
        }