private void btnLoadLevel_Click(object sender, EventArgs e) { //if (!SF64ROM.Instance.IsROMLoaded || SF64ROM.Instance.DMATable.Count <= levelDMAIndex) //{ // //Error message // MessageBox.Show("Rom file not loaded correctly, try reloading the ROM.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // return; //} //if (SF64ROM.Instance.DMATable[levelDMAIndex].DMAInfo.CFlag == 0x01) //{ // //Error message // MessageBox.Show("Specified level file is compressed, decompress before trying again.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // return; //} int dmaIndex = Convert.ToInt32(txtDMA.Text); int offset = Convert.ToInt32(txtOffset.Text, 16); F3DEXParser _f3dex = new F3DEXParser(); //_f3dex.InitInvalidModels(); byte[] dmaBytes = SF64ROM.Instance.DMATable[dmaIndex].GetAsBytes(); //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 & 3) != 0x0) || // dlist offset not 4 byte aligned // ((obj.DListOffset & 0xFF000000) == 0x80000000)) // dlist offset lies in ram, leave it alone for now // obj.DListOffset = 0x00; // else if (obj.DListOffset != 0x00 && (byte)((obj.DListOffset & 0xFF000000) >> 24) == 0x06) //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(levelBytes, obj.DListOffset); //KEEP AN EYE OUT FOR ANY CROSS-DMA REFERENCES // } //} try { _glControl.SingleObjectDLIndices = _f3dex.ReadGameObject(SF64ROM.Instance.DMATable[dmaIndex], dmaBytes, (uint)offset); } catch { _glControl.SingleObjectDLIndices = F3DEXParser.InvalidBox; } _glControl.SelectedObjectIndex = -1; _glControl.ReDraww(); }
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; }