Пример #1
0
        private bool DecompressDMA()
        {
            if(!IsROMLoaded)
            {
                return false;
            }

            for (int i = 0; i < DMATable.Count; i++)
            {
                DMAFile dma = DMATable[i];
                if(dma.DMAInfo.CFlag == 0x1)
                {
                    //compressed

                    //Decompress here
                    byte[] newDMAData;
                    if(StarFoxRomInfo.DecompressMIO0(dma.GetAsBytes(), out newDMAData))
                    {
                        dma.LoadFromBytes(newDMAData);

                        dma.DMAInfo.PEnd = dma.DMAInfo.VStart + (uint)newDMAData.Length;
                        dma.DMAInfo.PStart = dma.DMAInfo.VStart;
                        dma.DMAInfo.CFlag = 0x0;

                        _dmaTableDMA.DMATableEntries[i].CFlag = dma.DMAInfo.CFlag;
                    }
                    else
                    {
                        //Catastrophic failure, just quit out
                        return false;
                    }

                }
                else
                {
                    //uncompressed
                    dma.DMAInfo.PEnd = dma.DMAInfo.VStart + (dma.DMAInfo.PEnd - dma.DMAInfo.PStart);
                    dma.DMAInfo.PStart = dma.DMAInfo.VStart;
                }
            }

            Size = DMATable.Last().DMAInfo.PEnd;
            FixDMATable();

            return true;
        }
Пример #2
0
        public byte[] GetAsBytes()
        {
            if (!IsROMLoaded)
                return null;

            uint fullLength = DMATable.Last().DMAInfo.PEnd;

            //Rom length must be multiple of 0x400000
            if(fullLength % 0x400000 != 0)
                fullLength = (uint)Math.Ceiling((double)fullLength / 0x400000) * 0x400000;

            //Size = fullLength;

            byte[] newRomData = new byte[fullLength];

            foreach (DMAFile dma in DMATable)
            {
                Array.Copy(dma.GetAsBytes(), 0, newRomData, dma.DMAInfo.PStart, dma.DMAInfo.PEnd - dma.DMAInfo.PStart);
            }

            return newRomData;
        }
Пример #3
0
        public void LoadROMResources()
        {
            if (_resourcesLoaded)
                return;

            //Here we'll go through the level files/reference file, and then create the F3DEX objects and link them to the
            // simple object list in the reference file
            F3DEXParser _f3dex = new F3DEXParser();

            //_f3dex.InitInvalidModels();

            //Init the simple objects to use the invalid box dlist indices
            foreach (RefSimpleLevelObject obj in _referenceDMA.SimpleObjects)
            {
                obj.GLDisplayListOffset = F3DEXParser.InvalidBox;
            }

            //Init the simple objects to use the invalid box dlist indices
            foreach (RefAdvancedLevelObject obj in _referenceDMA.AdvancedObjects)
            {
                obj.GLDisplayListOffset = F3DEXParser.InvalidBox;
            }

            //Make a list of the level indices, just for optimization sake later on
            List<int> levelIndices = StarFoxRomInfo.LevelIndexAndDMAs.ToList();

            foreach (LevelDMAFile level in _levelDMAs)
            {
                byte[] levelBytes = level.GetAsBytes();

                Dictionary<int, byte[]> ramBytes = new Dictionary<int, byte[]>();
                int count = _referenceDMA.RAMTable.Count(r => r.Seg6Start == level.DMAInfo.PStart);
                int xs = count;
                RAMTableEntry ramInfo = _referenceDMA.RAMTable.FirstOrDefault(r => r.Seg6Start == level.DMAInfo.PStart);
                if (ramInfo != null)
                {
                    //Load it all in!!
                    DMAFile dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg1Start);
                    if(dma == null)
                        ramBytes.Add(1, null);
                    else
                        ramBytes.Add(1, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg2Start);
                    if (dma == null)
                        ramBytes.Add(2, null);
                    else
                        ramBytes.Add(2, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg3Start);
                    if (dma == null)
                        ramBytes.Add(3, null);
                    else
                        ramBytes.Add(3, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg4Start);
                    if (dma == null)
                        ramBytes.Add(4, null);
                    else
                        ramBytes.Add(4, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg5Start);
                    if (dma == null)
                        ramBytes.Add(5, null);
                    else
                        ramBytes.Add(5, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg6Start);
                    if (dma == null)
                        ramBytes.Add(6, null);
                    else
                        ramBytes.Add(6, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg7Start);
                    if (dma == null)
                        ramBytes.Add(7, null);
                    else
                        ramBytes.Add(7, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg8Start);
                    if (dma == null)
                        ramBytes.Add(8, null);
                    else
                        ramBytes.Add(8, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.Seg9Start);
                    if (dma == null)
                        ramBytes.Add(9, null);
                    else
                        ramBytes.Add(9, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.SegAStart);
                    if (dma == null)
                        ramBytes.Add(0xA, null);
                    else
                        ramBytes.Add(0xA, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.SegBStart);
                    if (dma == null)
                        ramBytes.Add(0xB, null);
                    else
                        ramBytes.Add(0xB, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.SegCStart);
                    if (dma == null)
                        ramBytes.Add(0xC, null);
                    else
                        ramBytes.Add(0xC, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.SegDStart);
                    if (dma == null)
                        ramBytes.Add(0xD, null);
                    else
                        ramBytes.Add(0xD, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.SegEStart);
                    if (dma == null)
                        ramBytes.Add(0xE, null);
                    else
                        ramBytes.Add(0xE, dma.GetAsBytes());

                    dma = SF64ROM.Instance.DMATable.SingleOrDefault(d => d.DMAInfo.PStart == ramInfo.SegFStart);
                    if (dma == null)
                        ramBytes.Add(0xF, null);
                    else
                        ramBytes.Add(0xF, dma.GetAsBytes());
                }

                foreach(SFLevelObject obj in level.LevelObjects)
                {
                    //We know that the 0x190 is the limit for the simple objects
                    if (obj.ID < 0x190)
                    {
                        obj.DListOffset = _referenceDMA.SimpleObjects[obj.ID].DListOffset;

                        // dlist offset sanity checks
                        if (((obj.DListOffset & 4) != 0x0) ||							// dlist offset not 4 byte aligned
                            ((obj.DListOffset & 0xFF000000) == 0x80000000) ||	// dlist offset lies in ram, leave it alone for now
                            ((obj.DListOffset & 0xFF000000) == 0x00000000))	// invalid dlist
                            obj.DListOffset = 0x00;

                        else
                        {
                            byte[] bytes = ramBytes[(int)((obj.DListOffset & 0xFF000000) >> 24)];

                            if (obj.DListOffset != 0x00 && bytes != null) //Need segment 6
                            {
                                //Load through the F3DEX parser, assign the DisplayListIndex to the Simple Object in the Reference DMA
                                //In the future we'll serialize the F3DEX commands/textures/vertices too, but for functional purposes
                                // we'll just use the blank binary
                                if (_referenceDMA.SimpleObjects[obj.ID].GLDisplayListOffset == F3DEXParser.InvalidBox)
                                    _referenceDMA.SimpleObjects[obj.ID].GLDisplayListOffset = _f3dex.ReadGameObject(level, bytes, obj.DListOffset); //KEEP AN EYE OUT FOR ANY CROSS-DMA REFERENCES
                            }
                        }
                    }
                    //We know that the 0x3E8 is the start of advanced objects
                    else if (obj.ID >= 0x3E8)
                    {
                        int scriptID = obj.ID - 0x3E8;

                        //Have to go digging around and creating the object scripts
                        int scriptStartOffset = StarFoxRomInfo.LevelIndexAndAdvItemIndex[levelIndices.IndexOf(DMATable.IndexOf(level))];

                        if (scriptStartOffset == 0)
                            continue;

                        SFAdvancedObjectScript script = level.LevelScripts.SingleOrDefault(s => s.ScriptIndex == scriptID);

                        if (script == null)
                        {
                            int scriptOffset = ByteHelper.ReadInt(levelBytes, scriptStartOffset + scriptID * 0x4);

                            int scriptOffsetShort = scriptOffset & 0x00FFFFFF;

                            int size = 0;
                            uint nextLine = 0x0;

                            do
                            {
                                nextLine = ByteHelper.ReadUInt(levelBytes, scriptOffsetShort + size);
                                size += 4;
                            } while (nextLine != 0xFE000000);

                            byte[] scriptBytes = new byte[size];
                            Array.Copy(levelBytes, scriptOffsetShort, scriptBytes, 0, size);

                            script = new SFAdvancedObjectScript(scriptOffset, scriptID, scriptBytes);

                            level.LevelScripts.Add(script);

                        }

                        obj.AdvancedScript = script;

                        if (script.AdvancedObjectIndex != -1 && script.AdvancedObjectIndex < _referenceDMA.AdvancedObjects.Count)
                        {
                            obj.DListOffset = _referenceDMA.AdvancedObjects[script.AdvancedObjectIndex].DListOffset;

                            // dlist offset sanity checks
                            if (((obj.DListOffset & 4) != 0x0) ||							// dlist offset not 4 byte aligned
                                ((obj.DListOffset & 0xFF000000) == 0x80000000) ||	// dlist offset lies in ram, leave it alone for now
                                ((obj.DListOffset & 0xFF000000) == 0x00000000))	// invalid dlist
                                obj.DListOffset = 0x00;

                            else
                            {
                                byte[] bytes = ramBytes[(int)((obj.DListOffset & 0xFF000000) >> 24)];

                                if (obj.DListOffset != 0x00 && bytes != null) //Need segment 6
                                {
                                    //Load through the F3DEX parser, assign the DisplayListIndex to the Simple Object in the Reference DMA
                                    //In the future we'll serialize the F3DEX commands/textures/vertices too, but for functional purposes
                                    // we'll just use the blank binary
                                    if (_referenceDMA.AdvancedObjects[script.AdvancedObjectIndex].GLDisplayListOffset == F3DEXParser.InvalidBox)
                                        _referenceDMA.AdvancedObjects[script.AdvancedObjectIndex].GLDisplayListOffset = _f3dex.ReadGameObject(level, bytes, obj.DListOffset); //KEEP AN EYE OUT FOR ANY CROSS-DMA REFERENCES
                                }
                            }
                        }
                    }
                }
            }

            _resourcesLoaded = true;
        }
Пример #4
0
        private bool BytesToDMATable(byte[] data, Endianness RomEndianness)
        {
            //Using the DMA Table offset, break up the file into its constituent DMA blocks.
            if (DMATableOffset == 0x0)
            {
                return false;
            }

            IsCompressed = false;

            DMATable.Clear();
            _levelDMAs.Clear();
            _headerDMA = null;
            _dmaTableDMA = null;
            _referenceDMA = null;

            int CurrentPos = (int)DMATableOffset;

            try
            {
                while (CurrentPos < data.Length - 16)
                {
                    uint VStart = ByteHelper.ReadUInt(data, CurrentPos, RomEndianness);
                    uint PStart = ByteHelper.ReadUInt(data, CurrentPos + 4, RomEndianness);
                    uint PEnd = ByteHelper.ReadUInt(data, CurrentPos + 8, RomEndianness);
                    uint CompFlag = ByteHelper.ReadUInt(data, CurrentPos + 12, RomEndianness);

                    //End of the DMA Header
                    if ((PStart == 0x00) && (PEnd == 0x00)) break;

                    //Create the actual data
                    byte[] dmaBytes = new byte[PEnd - PStart];
                    Array.Copy(data, PStart, dmaBytes, 0, dmaBytes.Length);

                    DMAFile entry;
                    switch(DMATable.Count) //Should act as an index for the current dma file
                    {
                        case 0: //Header DMA
                            entry = new HeaderDMAFile(dmaBytes, DMATable.Count);
                            _headerDMA = (HeaderDMAFile)entry;
                            break;
                        case 1: //Reference DMA
                            entry = new ReferenceDMAFile(dmaBytes, DMATable.Count);
                            _referenceDMA = (ReferenceDMAFile)entry;
                            break;
                        case 2: //DMA Table DMA
                            entry = new DMATableDMAFile(dmaBytes, DMATable.Count);
                            _dmaTableDMA = (DMATableDMAFile)entry;
                            break;
                        case 54: //Dialogue DMA
                            entry = new DialogueDMAFile(dmaBytes, DMATable.Count);
                            _dialogueDMA = (DialogueDMAFile)entry;
                            break;
                        //case 12: Appears broken right now, the Game Object table is set up differently than the other files. Possibly a prototype setup?
                        case 18:
                        case 19:
                        case 20:
                        case 26:
                        case 27:
                        case 28:
                        case 29:
                        case 30:
                        case 31:
                        case 33:
                        case 34:
                        case 35:
                        case 36:
                        case 37:
                        case 38:
                        case 39:
                        case 47:
                        case 53:
                            entry = new LevelDMAFile(dmaBytes, DMATable.Count, (int)_referenceDMA.LevelHeaderOffsets[StarFoxRomInfo.DMATableToLevelIndex(DMATable.Count)], 
                                (int)_referenceDMA.LevelInfoOffsets[StarFoxRomInfo.DMATableToLevelIndex(DMATable.Count)]);
                            _levelDMAs.Add(entry as LevelDMAFile);
                            break;
                        default: //Others
                            entry = new DMAFile(dmaBytes, DMATable.Count);
                            break;
                    }

                    DMATable.Add(entry);

                    CurrentPos += 16;
                }

                //Now set the DMA Headers
                if (_dmaTableDMA != null)
                {
                    for (int i = 0; i < DMATable.Count; i++)
                    {
                        DMATable[i].DMAInfo = _dmaTableDMA.DMATableEntries[i];

                        if (DMATable[i].DMAInfo.CFlag == 1)
                            IsCompressed = true;
                    }
                }

                if (_referenceDMA != null && _levelDMAs.Count > 0)
                {
                    //Parse out the F3DEX info
                    //LoadROMResources();
                }
            }
            catch
            {
                //Error log entry?
                return false;
            }

            return true;

            ////Automatically decompress on loading?
            //if (IsCompressed)
            //{
            //    if (DecompressDMA())
            //    {
            //        FixCRC();
            //    }
            //}
        }