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; }
public RAMTableEntryInfo(RAMTableEntry ram) { _ram = ram; }
public override bool LoadFromBytes(byte[] bytes) { base.LoadFromBytes(bytes); if (LevelInfoOffsets == null) { LevelInfoOffsets = new List <uint>(); } if (LevelHeaderOffsets == null) { LevelHeaderOffsets = new List <uint>(); } LevelInfoOffsets.Clear(); LevelHeaderOffsets.Clear(); //Level Info Offsets - I wish I didn't have to hardcode these values' locations, but oh well byte[] offsetData; _dmaData.TakeMemory(LEVEL_INFO_OFFSETS_LOCATION, LEVEL_COUNT * sizeof(uint), out offsetData); for (int i = 0; i < LEVEL_COUNT; i++) { LevelInfoOffsets.Add(ByteHelper.ReadUInt(offsetData, i * sizeof(uint))); } _dmaData.TakeMemory(LEVEL_HEADER_OFFSETS_LOCATION, LEVEL_COUNT * sizeof(uint), out offsetData); for (int i = 0; i < LEVEL_COUNT; i++) { LevelHeaderOffsets.Add(ByteHelper.ReadUInt(offsetData, i * sizeof(uint))); } //Simple objects if (SimpleObjects == null) { SimpleObjects = new List <RefSimpleLevelObject>(); } SimpleObjects.Clear(); for (int i = 0; i < SIMPLE_OBJECTS_COUNT; i++) { int index = SIMPLE_OBJECTS_LOCATION + i * RefSimpleLevelObject.Size; _dmaData.TakeMemory(index, RefSimpleLevelObject.Size, out offsetData); RefSimpleLevelObject newObj = new RefSimpleLevelObject(index, offsetData); SimpleObjects.Add(newObj); } //Advanced objects if (AdvancedObjects == null) { AdvancedObjects = new List <RefAdvancedLevelObject>(); } AdvancedObjects.Clear(); for (int i = 0; i < ADVANCED_OBJECTS_COUNT; i++) { int index = ADVANCED_OBJECTS_LOCATION + i * RefAdvancedLevelObject.Size; _dmaData.TakeMemory(index, RefAdvancedLevelObject.Size, out offsetData); RefAdvancedLevelObject newObj = new RefAdvancedLevelObject(index, offsetData); AdvancedObjects.Add(newObj); } //RAM table if (RAMTable == null) { RAMTable = new List <RAMTableEntry>(); } RAMTable.Clear(); for (int i = 0; i < RAM_TABLE_COUNT; i++) { int index = RAM_TABLE_LOCATION + i * RAMTableEntry.Size; _dmaData.TakeMemory(index, RAMTableEntry.Size, out offsetData); RAMTableEntry newObj = new RAMTableEntry(index, offsetData); RAMTable.Add(newObj); } return(true); }