Пример #1
0
        public ROMHandler(string fn)
        {
#if !DEBUG
            try
#endif
            {
reload:
                DMATableAddress = FileNameTableAddress = SceneTableAddress = -1;

                Filename = fn;

                /* Initialize segment and rendering systems */
                SegmentMapping = new Hashtable();
                Renderer       = new F3DEX2Interpreter(this);

                /* Read ROM */
                BinaryReader br = new BinaryReader(File.Open(fn, FileMode.Open, FileAccess.Read, FileShare.Read));
                if (br.BaseStream.Length < MinROMSize)
                {
                    throw new ROMHandlerException(string.Format("File size is less than {0}MB; ROM appears to be invalid.", MinROMSize / 0x100000));
                }
                Data = new byte[br.BaseStream.Length];
                br.Read(Data, 0, (int)br.BaseStream.Length);
                br.Close();

                /* Detect byte order */
                DetectByteOrder();

                if (DetectedByteOrder != ByteOrder.BigEndian)
                {
                    if (MessageBox.Show("The ROM file you have selected uses an incompatible byte order, and needs to be converted to Big Endian format to be used." + Environment.NewLine + Environment.NewLine +
                                        "Convert the ROM now? (You will be asked for the target filename; the converted ROM will also be reloaded.)", "Byte Order Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        /* Ask for new filename */
                        string fnnew = GUIHelpers.ShowSaveFileDialog("Nintendo 64 ROMs (*.z64;*.bin)|*.z64;*.bin|All Files (*.*)|*.*");
                        if (fnnew != string.Empty)
                        {
                            fn = fnnew;

                            /* Perform byte order conversion */
                            byte[] datanew = new byte[Data.Length];
                            byte[] conv    = null;
                            for (int i = 0, j = 0; i < Data.Length; i += 4, j += 4)
                            {
                                if (DetectedByteOrder == ByteOrder.MiddleEndian)
                                {
                                    conv = new byte[4] {
                                        Data[i + 1], Data[i], Data[i + 3], Data[i + 2]
                                    }
                                }
                                ;
                                else if (DetectedByteOrder == ByteOrder.LittleEndian)
                                {
                                    conv = new byte[4] {
                                        Data[i + 3], Data[i + 2], Data[i + 1], Data[i]
                                    }
                                }
                                ;
                                Buffer.BlockCopy(conv, 0, datanew, j, conv.Length);
                            }

                            /* Save converted ROM, then reload it */
                            BinaryWriter bw = new BinaryWriter(File.Create(fn));
                            bw.Write(datanew);
                            bw.Close();

                            goto reload;
                        }
                    }
                    else
                    {
                        /* Wrong byte order, no conversion performed */
                        throw new ByteOrderException(string.Format("Incompatible byte order {0} detected; ROM cannot be used.", DetectedByteOrder));
                    }
                }
                else
                {
                    /* Read header */
                    ReadROMHeader();

                    /* Create XML actor definition reader */
                    XMLActorDefReader = new XMLActorDefinitionReader(Path.Combine("XML", "ActorDefinitions", GameID.Substring(1, 2)));

                    if (XMLActorDefReader.Definitions.Count > 0)
                    {
                        /* Create remaining XML-related objects */
                        XMLActorNames  = new XMLHashTableReader(Path.Combine("XML", "GameDataGeneric", GameID.Substring(1, 2)), "ActorNames.xml");
                        XMLObjectNames = new XMLHashTableReader(Path.Combine("XML", "GameDataGeneric", GameID.Substring(1, 2)), "ObjectNames.xml");
                        XMLSongNames   = new XMLHashTableReader(Path.Combine("XML", "GameDataGeneric", GameID.Substring(1, 2)), "SongNames.xml");

                        XMLSceneNames        = new XMLHashTableReader(Path.Combine("XML", "GameDataSpecific", string.Format("{0}{1:X1}", GameID, Version)), "SceneNames.xml");
                        XMLRoomNames         = new XMLHashTableReader(Path.Combine("XML", "GameDataSpecific", string.Format("{0}{1:X1}", GameID, Version)), "RoomNames.xml");
                        XMLStageDescriptions = new XMLHashTableReader(Path.Combine("XML", "GameDataSpecific", string.Format("{0}{1:X1}", GameID, Version)), "StageDescriptions.xml");

                        /* Determine if ROM uses z64tables hack */
                        HasZ64TablesHack = (Version == 15 && Endian.SwapUInt32(BitConverter.ToUInt32(Data, 0x1238)) != 0x0C00084C);

                        /* Find and read build information, DMA table, etc. */
                        FindBuildInfo();
                        FindDMATable();
                        FindFileNameTable();
                        ReadDMATable();
                        ReadFileNameTable();

                        /* Try to identify files */
                        foreach (DMATableEntry dte in Files)
                        {
                            dte.Identify(this);
                        }

                        /* Find the code file */
                        FindCodeFile();

                        /* Find other Zelda-specific stuff */
                        FindActorTable();
                        FindObjectTable();
                        FindSceneTable();
                        ReadEntranceTable();

                        /* Some sanity checking & exception handling*/
                        if (Scenes == null || Scenes.Count == 0)
                        {
                            throw new ROMHandlerException("No valid scenes could be recognized in the ROM.");
                        }

                        /* Done */
                        Loaded = true;
                    }
                }
            }
#if !DEBUG
            catch (Exception ex)
            {
                Loaded = false;
                if (MessageBox.Show(ex.Message + "\n\n" + "Show detailed information?", "Exception", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                {
                    MessageBox.Show(ex.ToString(), "Exception Details", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
#endif
        }