private void UpdateEntries(String msg, int index) { m_MsgData[index] = msg; m_ShortVersions[index] = ShortVersion(msg, index); int lengthDif = EncodeString(msg).Count - m_StringLengths[index]; m_StringLengths[index] += lengthDif; //Make or remove room for the new string if needed (don't need to for last entry) if (lengthDif > 0 && index != m_MsgData.Length - 1) { uint curStringStart = m_StringHeaderData[index] + m_DAT1Start; uint nextStringStart = m_StringHeaderData[index + 1] + m_DAT1Start; byte[] followingData = file.ReadBlock(nextStringStart, (uint)(file.m_Data.Length - nextStringStart)); for (int i = (int)curStringStart; i < (int)nextStringStart + lengthDif; i++) { file.Write8((uint)i, 0);// Fill the gap with zeroes } file.WriteBlock((uint)(nextStringStart + lengthDif), followingData); } else if (lengthDif < 0 && index != m_MsgData.Length - 1) { // lengthDif is negative, -- + uint nextStringStart = m_StringHeaderData[index + 1] + m_DAT1Start; byte[] followingData = file.ReadBlock(nextStringStart, (uint)(file.m_Data.Length - nextStringStart)); file.WriteBlock((uint)(nextStringStart + lengthDif), followingData); int oldSize = file.m_Data.Length; Array.Resize(ref file.m_Data, oldSize + lengthDif);// Remove duplicate data at end of file } // Update pointers to string entry data if (lengthDif != 0) { for (int i = index + 1; i < m_MsgData.Length; i++) { if (lengthDif > 0) { m_StringHeaderData[i] += (uint)lengthDif; } else if (lengthDif < 0) { m_StringHeaderData[i] = (uint)(m_StringHeaderData[i] + lengthDif); } file.Write32(m_StringHeaderAddr[i], m_StringHeaderData[i]); file.Write16(m_StringWidthAddr[i], m_StringWidth[i]); file.Write16(m_StringHeightAddr[i], m_StringHeight[i]); } } // Update total file size file.Write32(0x08, (uint)(int)(file.Read32(0x08) + lengthDif)); // Update DAT1 size file.Write32(m_DAT1Start - 0x04, (uint)(int)(file.Read32(m_DAT1Start - 0x04) + lengthDif)); }
public byte[] m_Reserved; // unused, 0s (16) public SDATHeader(NitroFile sdat) { m_Type = sdat.ReadBlock(0x00, 4); m_Magic = sdat.Read32(0x04); m_FileSize = sdat.Read32(0x08); m_Size = sdat.Read16(0x0C); m_Block = sdat.Read16(0x0E); m_SymbolOffset = sdat.Read32(0x10); m_SymbolSize = sdat.Read32(0x14); m_InfoOffset = sdat.Read32(0x18); m_InfoSize = sdat.Read32(0x1C); m_FatOffset = sdat.Read32(0x20); m_FatSize = sdat.Read32(0x24); m_FileBlockOffset = sdat.Read32(0x28); m_FileBlockSize = sdat.Read32(0x2C); m_Reserved = sdat.ReadBlock(0x30, 16); }
public byte[] m_Type; // 'SDAT' (4) #endregion Fields #region Constructors public SDATHeader(NitroFile sdat) { m_Type = sdat.ReadBlock(0x00, 4); m_Magic = sdat.Read32(0x04); m_FileSize = sdat.Read32(0x08); m_Size = sdat.Read16(0x0C); m_Block = sdat.Read16(0x0E); m_SymbolOffset = sdat.Read32(0x10); m_SymbolSize = sdat.Read32(0x14); m_InfoOffset = sdat.Read32(0x18); m_InfoSize = sdat.Read32(0x1C); m_FatOffset = sdat.Read32(0x20); m_FatSize = sdat.Read32(0x24); m_FileBlockOffset = sdat.Read32(0x28); m_FileBlockSize = sdat.Read32(0x2C); m_Reserved = sdat.ReadBlock(0x30, 16); }
public SDATInfo(NitroFile sdat, uint offset) { m_Offset = offset; m_Type = sdat.ReadString(m_Offset + 0x00, 4).ToCharArray(); m_Size = sdat.Read32(m_Offset + 0x04); m_RecordOffset = new uint[8]; for (int i = 0; i < 8; i++) { m_RecordOffset[i] = sdat.Read32(m_Offset + 0x08 + (uint)(i * 4)); } m_Reserved = sdat.ReadBlock(m_Offset + 0x28, 24); m_Records = new SDATInfoRecord[8]; for (int i = 0; i < 8; i++) { m_Records[i] = new SDATInfoRecord(sdat, m_Offset + m_RecordOffset[i]); } m_Records0SEQ = new SDATInfoSEQ[m_Records[0].m_Count]; for (int i = 0; i < m_Records[0].m_Count; i++) { m_Records0SEQ[i] = new SDATInfoSEQ(sdat, m_Offset + m_Records[0].m_EntryOffset[i]); } m_Records1SEQARC = new SDATInfoSEQARC[m_Records[1].m_Count]; for (int i = 0; i < m_Records[1].m_Count; i++) { m_Records1SEQARC[i] = new SDATInfoSEQARC(sdat, m_Offset + m_Records[1].m_EntryOffset[i]); } m_Records2BANK = new SDATInfoBANK[m_Records[2].m_Count]; for (int i = 0; i < m_Records[2].m_Count; i++) { m_Records2BANK[i] = new SDATInfoBANK(sdat, m_Offset + m_Records[2].m_EntryOffset[i]); } m_Records3WAVEARC = new SDATInfoWAVEARC[m_Records[3].m_Count]; for (int i = 0; i < m_Records[3].m_Count; i++) { m_Records3WAVEARC[i] = new SDATInfoWAVEARC(sdat, m_Offset + m_Records[3].m_EntryOffset[i]); } m_Records4PLAYER = new SDATInfoPLAYER[m_Records[4].m_Count]; for (int i = 0; i < m_Records[4].m_Count; i++) { m_Records4PLAYER[i] = new SDATInfoPLAYER(sdat, m_Offset + m_Records[4].m_EntryOffset[i]); } m_Records5GROUP = new SDATInfoGROUP[m_Records[5].m_Count]; for (int i = 0; i < m_Records[5].m_Count; i++) { m_Records5GROUP[i] = new SDATInfoGROUP(sdat, m_Offset + m_Records[5].m_EntryOffset[i]); } m_Records6PLAYER2 = new SDATInfoPLAYER2[m_Records[6].m_Count]; for (int i = 0; i < m_Records[6].m_Count; i++) { m_Records6PLAYER2[i] = new SDATInfoPLAYER2(sdat, m_Offset + m_Records[6].m_EntryOffset[i]); } m_Records7STREAM = new SDATInfoSTREAM[m_Records[7].m_Count]; for (int i = 0; i < m_Records[7].m_Count; i++) { m_Records7STREAM[i] = new SDATInfoSTREAM(sdat, m_Offset + m_Records[7].m_EntryOffset[i]); } }
public SDATInfoSEQ(NitroFile sdat, uint offset) { m_File = sdat; m_Offset = offset; m_FileID = sdat.Read32(m_Offset + 0x00); m_Bank = sdat.Read16(m_Offset + 0x04); m_Volume = sdat.Read8(m_Offset + 0x06); m_ChannelPriority = sdat.Read8(m_Offset + 0x07); m_PlayerPriority = sdat.Read8(m_Offset + 0x08); m_PlayerNumber = sdat.Read8(m_Offset + 0x09); m_Unknown2 = sdat.ReadBlock(m_Offset + 0x0A, 2); }
public void LoadTexture() { //Console.WriteLine($"offset = 0x{Convert.ToString(offset, 16)}"); if (m_ParticleTexFile.Read32(0x0) != 0x53505420) { MessageBox.Show(string.Format("This SPT file is invalid."), "Bad texture"); Close(); return; } uint flags = m_ParticleTexFile.Read32(0x04); uint texelArrSize = m_ParticleTexFile.Read32(0x08); uint palOffset = m_ParticleTexFile.Read32(0x0c); uint palSize = m_ParticleTexFile.Read32(0x10); uint totalSize = m_ParticleTexFile.Read32(0x1c); byte[] texels = m_ParticleTexFile.ReadBlock(0x20, texelArrSize); byte[] palette = m_ParticleTexFile.ReadBlock(palOffset, palSize); int width = 1 << (((int)flags >> 4 & 0xf) + 3); int height = 1 << (((int)flags >> 8 & 0xf) + 3); bool color0Transp = ((flags & 0x8) | (flags & 0x10000)) != 0; int type = (int)flags & 0x7; Particle.Texture.RepeatMode repeatX = (flags & 0x4000) != 0 ? Particle.Texture.RepeatMode.FLIP : (flags & 0x1000) != 0 ? Particle.Texture.RepeatMode.REPEAT : Particle.Texture.RepeatMode.CLAMP; Particle.Texture.RepeatMode repeatY = (flags & 0x8000) != 0 ? Particle.Texture.RepeatMode.FLIP : (flags & 0x2000) != 0 ? Particle.Texture.RepeatMode.REPEAT : Particle.Texture.RepeatMode.CLAMP; m_Texture = new Particle.Texture(texels, palette, width, height, (byte)(color0Transp ? 1 : 0), type, repeatX, repeatY, 0); }
char[] m_Type; // 'INFO' #endregion Fields #region Constructors public SDATInfo(NitroFile sdat, uint offset) { m_Offset = offset; m_Type = sdat.ReadString(m_Offset + 0x00, 4).ToCharArray(); m_Size = sdat.Read32(m_Offset + 0x04); m_RecordOffset = new uint[8]; for (int i = 0; i < 8; i++) m_RecordOffset[i] = sdat.Read32(m_Offset + 0x08 + (uint)(i * 4)); m_Reserved = sdat.ReadBlock(m_Offset + 0x28, 24); m_Records = new SDATInfoRecord[8]; for (int i = 0; i < 8; i++) { m_Records[i] = new SDATInfoRecord(sdat, m_Offset + m_RecordOffset[i]); } m_Records0SEQ = new SDATInfoSEQ[m_Records[0].m_Count]; for (int i = 0; i < m_Records[0].m_Count; i++) { m_Records0SEQ[i] = new SDATInfoSEQ(sdat, m_Offset + m_Records[0].m_EntryOffset[i]); } m_Records1SEQARC = new SDATInfoSEQARC[m_Records[1].m_Count]; for (int i = 0; i < m_Records[1].m_Count; i++) { m_Records1SEQARC[i] = new SDATInfoSEQARC(sdat, m_Offset + m_Records[1].m_EntryOffset[i]); } m_Records2BANK = new SDATInfoBANK[m_Records[2].m_Count]; for (int i = 0; i < m_Records[2].m_Count; i++) { m_Records2BANK[i] = new SDATInfoBANK(sdat, m_Offset + m_Records[2].m_EntryOffset[i]); } m_Records3WAVEARC = new SDATInfoWAVEARC[m_Records[3].m_Count]; for (int i = 0; i < m_Records[3].m_Count; i++) { m_Records3WAVEARC[i] = new SDATInfoWAVEARC(sdat, m_Offset + m_Records[3].m_EntryOffset[i]); } m_Records4PLAYER = new SDATInfoPLAYER[m_Records[4].m_Count]; for (int i = 0; i < m_Records[4].m_Count; i++) { m_Records4PLAYER[i] = new SDATInfoPLAYER(sdat, m_Offset + m_Records[4].m_EntryOffset[i]); } m_Records5GROUP = new SDATInfoGROUP[m_Records[5].m_Count]; for (int i = 0; i < m_Records[5].m_Count; i++) { m_Records5GROUP[i] = new SDATInfoGROUP(sdat, m_Offset + m_Records[5].m_EntryOffset[i]); } m_Records6PLAYER2 = new SDATInfoPLAYER2[m_Records[6].m_Count]; for (int i = 0; i < m_Records[6].m_Count; i++) { m_Records6PLAYER2[i] = new SDATInfoPLAYER2(sdat, m_Offset + m_Records[6].m_EntryOffset[i]); } m_Records7STREAM = new SDATInfoSTREAM[m_Records[7].m_Count]; for (int i = 0; i < m_Records[7].m_Count; i++) { m_Records7STREAM[i] = new SDATInfoSTREAM(sdat, m_Offset + m_Records[7].m_EntryOffset[i]); } }
private void loadExternalToolStripMenuItem_Click(object sender, EventArgs e) { int texDefID = lbxTexDef.SelectedIndex; // this shouldn't happen but you never know if (texDefID == -1) { return; } m_ROMFileSelect.ReInitialize("Select a SPT file to load", new String[] { ".spt" }); DialogResult result = m_ROMFileSelect.ShowDialog(); if (result != DialogResult.OK) { return; } else { try { NitroFile SPT = Program.m_ROM.GetFileFromName(m_ROMFileSelect.m_SelectedFile); if (SPT.Read32(0x0) != 0x53505420) { throw new Exception("Invalid SPT header."); } uint flags = SPT.Read32(0x04); uint texelArrSize = SPT.Read32(0x08); uint palOffset = SPT.Read32(0x0c); uint palSize = SPT.Read32(0x10); uint totalSize = SPT.Read32(0x1c); byte[] texels = SPT.ReadBlock(0x20, texelArrSize); byte[] palette = SPT.ReadBlock(palOffset, palSize); int width = 1 << (((int)flags >> 4 & 0xf) + 3); int height = 1 << (((int)flags >> 8 & 0xf) + 3); bool color0Transp = ((flags & 0x8) | (flags & 0x10000)) != 0; int type = (int)flags & 0x7; Particle.Texture.RepeatMode repeatX = (flags & 0x4000) != 0 ? Particle.Texture.RepeatMode.FLIP : (flags & 0x1000) != 0 ? Particle.Texture.RepeatMode.REPEAT : Particle.Texture.RepeatMode.CLAMP; Particle.Texture.RepeatMode repeatY = (flags & 0x8000) != 0 ? Particle.Texture.RepeatMode.FLIP : (flags & 0x2000) != 0 ? Particle.Texture.RepeatMode.REPEAT : Particle.Texture.RepeatMode.CLAMP; m_TexDefs[texDefID].Unload(); m_TexDefs[texDefID] = new Particle.Texture(texels, palette, width, height, (byte)(color0Transp ? 1 : 0), type, repeatX, repeatY, texDefID); m_TexDefs[texDefID].Load(); UpdateParticleTextures(texDefID); } catch (Exception ex) { MessageBox.Show("Failed to load external SPT. Details:\n" + ex.Message, "Failed to load SPT"); } RefreshImage(); PopulatePaletteSettings(); } }