Imports System Imports System.IO Imports System.Text Imports System.Media Imports VB = Microsoft.VisualBasic 'These functions are based off the ones found in this project: https://github.com/doom-desire/Cry-Editor 'Credit goes to doom-desire for these functions. Module CryFunctions Structure Cry Public Index As Integer Public Offset As Integer Public Compressed As Boolean Public Looped As Boolean Public SampleRate As Integer Public LoopStart As Integer Public Size As Integer Public Data As SByte() End Structure Public Function LoadCry(index As Integer, cryTable As Integer) As Cry 'If ledrom Is Nothing Then ' Return False 'End If ' load cry table entry 'ledrom.Seek(cryTable + index * 12) 'Dim someValue = ledrom.ReadInt32() 'Dim cryOffset = ledrom.ReadPointer() 'Dim cryShape = ledrom.ReadInt32() Dim CryToLoad As New Cry With { .Index = index } Dim convIndex As Integer = -1 If index > 276 Then Dim offset As Integer = Int32.Parse((GetString(GetINIFileLocation(), header, "CryConversionTable", "")), System.Globalization.NumberStyles.HexNumber) convIndex = Int32.Parse((ReverseHEX(ReadHEX(LoadedROM, ((offset)) + ((index - 276) * 2), 2))), System.Globalization.NumberStyles.HexNumber) End If Dim someValue = Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryTable) + (index * 12), 4))), System.Globalization.NumberStyles.HexNumber) Dim cryOffset = (Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryTable) + (index * 12) + 4, 4))), System.Globalization.NumberStyles.HexNumber) - &H8000000) Dim cryShape = Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryTable) + (index * 12) + 8, 4))), System.Globalization.NumberStyles.HexNumber) 'If cryOffset = 0 Then ' Return False 'End If ' load cry data 'ledrom.Seek(cryOffset) CryToLoad.Offset = cryOffset If convIndex <> -1 Then someValue = Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryTable) + (convIndex * 12), 4))), System.Globalization.NumberStyles.HexNumber) cryOffset = (Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryTable) + (convIndex * 12) + 4, 4))), System.Globalization.NumberStyles.HexNumber) - &H8000000) cryShape = Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryTable) + (convIndex * 12) + 8, 4))), System.Globalization.NumberStyles.HexNumber) CryToLoad.Offset = cryOffset End If 'CryToLoad.Compressed = ledrom.ReadUInt16() = &H1 'CryToLoad.Looped = ledrom.ReadUInt16() = &H4000 'CryToLoad.SampleRate = ledrom.ReadInt32() >> 10 'CryToLoad.LoopStart = ledrom.ReadInt32() 'CryToLoad.Size = ledrom.ReadInt32() + 1 CryToLoad.Compressed = Int16.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryOffset) + 0, 2))), System.Globalization.NumberStyles.HexNumber) = &H1 CryToLoad.Looped = Int16.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryOffset) + 2, 2))), System.Globalization.NumberStyles.HexNumber) = &H4000 CryToLoad.SampleRate = Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryOffset) + 4, 4))), System.Globalization.NumberStyles.HexNumber) >> 10 CryToLoad.LoopStart = Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryOffset) + 8, 4))), System.Globalization.NumberStyles.HexNumber) CryToLoad.Size = Int32.Parse(ReverseHEX((ReadHEX(LoadedROM, (cryOffset) + 12, 4))), System.Globalization.NumberStyles.HexNumber) + 1 If Not CryToLoad.Compressed Then ' uncompressed, 1 sample per 1 byte of size CryToLoad.Data = New SByte(CryToLoad.Size - 1) {} Dim cryToLoadTemp As String = ReadHEX(LoadedROM, (cryOffset) + 16, CryToLoad.Size - 1) For g As Integer = 0 To CryToLoad.Size - 2 CryToLoad.Data(g) = ByteToSignedInt("&H" & cryToLoadTemp.Substring(g * 2, 2)) Next 'For g As Integer = 0 To CryToLoad.Size - 1 ' CryToLoad.Data(g) = ByteToSignedInt("&H" & (ReadHEX(LoadedROM, (cryOffset) + 16 + g, 1))) 'Next Else ' compressed, a bit of a hassle Dim lookup = New SByte() {0, 1, 4, 9, 16, 25, 36, 49, -64, -49, -36, -25, -16, -9, -4, -1} Dim start = (cryOffset) + 16 Dim offtrack = (cryOffset) + 16 Dim alignment As Integer = 0, size As Integer = 0 Dim pcmLevel As SByte = 0 Dim pcmTemp As Int16 = 0 Dim data = New List(Of SByte)() Dim cryData As String = (ReadHEX(LoadedROM, offtrack, CryToLoad.Size)) offtrack = 0 While True If alignment = 0 Then pcmLevel = ByteToSignedInt("&H" & cryData.Substring(offtrack, 2)) '(ReadHEX(LoadedROM, offtrack, 1))) pcmTemp = pcmLevel offtrack = offtrack + 2 '1 data.Add(pcmLevel) alignment = &H20 End If Dim input As Byte = ("&H" & cryData.Substring(offtrack, 2)) '(ReadHEX(LoadedROM, offtrack, 1))) offtrack = offtrack + 2 '1 If alignment < &H20 Then If Int16.Parse(pcmLevel) + lookup(input >> 4) < -128 Then pcmLevel = 128 + lookup(input >> 4) ElseIf Int16.Parse(pcmLevel) + lookup(input >> 4) > 127 Then pcmLevel = -129 + lookup(input >> 4) Else pcmLevel += lookup(input >> 4) End If data.Add(pcmLevel) End If ' second nybble If Int16.Parse(pcmLevel) + lookup(input And &HF) < -128 Then pcmLevel = 128 + lookup(input And &HF) ElseIf Int16.Parse(pcmLevel) + lookup(input And &HF) > 127 Then pcmLevel = -129 + lookup(input And &HF) Else pcmLevel += lookup(input And &HF) End If data.Add(pcmLevel) ' exit when currentSize >= cry.Size size += 2 If size >= CryToLoad.Size Then Exit While End If alignment -= 1 End While CryToLoad.Data = data.ToArray() ' bytes needed to recompress CryToLoad.Size = offtrack / 2 'offtrack - start End If Return CryToLoad End Function Public Function GetCryImage(cry As Cry) As Bitmap Dim cryImage As Bitmap If GetString(AppPath & "GBAPGESettings.ini", "Settings", "DisableCryImage", "0") = "1" Then cryImage = New Bitmap(128, 128) Else cryImage = New Bitmap(cry.Data.Length, 128) Using g = Graphics.FromImage(cryImage) For i As Integer = 1 To cry.Data.Length - 1 g.DrawLine(Pens.Green, i - 1, 64 + cry.Data(i - 1), i, 64 + cry.Data(i)) Next End Using End If Return cryImage End Function Public Sub PlayCry(cry As Cry) ' TODO: we could do this in another thread :O If cry.Offset = 0 Then Exit Sub End If Using stream = New MemoryStream() ' "save" the cry to a memorystream Using writer As BinaryWriter = New BinaryWriter(stream, Encoding.ASCII, True) ' RIFF header writer.Write(Encoding.ASCII.GetBytes("RIFF")) writer.Write(0) writer.Write(Encoding.ASCII.GetBytes("WAVE")) ' fmt chunk writer.Write(Encoding.ASCII.GetBytes("fmt ")) writer.Write(16) writer.Write(CUShort(1)) writer.Write(CUShort(1)) writer.Write(cry.SampleRate) writer.Write(cry.SampleRate) writer.Write(CUShort(1)) writer.Write(CUShort(8)) ' data chunk writer.Write(Encoding.ASCII.GetBytes("data")) writer.Write(cry.Data.Length) For Each sample As SByte In cry.Data writer.Write(CByte(sample + &H80)) Next ' fix header writer.Seek(4, SeekOrigin.Begin) writer.Write(CInt(writer.BaseStream.Length) - 8) End Using ' play it via a soundplayer stream.Seek(0L, SeekOrigin.Begin) Using player = New SoundPlayer(stream) player.Load() player.Play() End Using End Using End Sub Public Sub ExportCry(filename As String, cry As Cry) If cry.Offset = 0 Then Return End If ' http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/wave.html ' http://soundfile.sapp.org/doc/WaveFormat/ Using writer = New BinaryWriter(File.Create(filename)) ' RIFF header writer.Write(Encoding.ASCII.GetBytes("RIFF")) ' file ID writer.Write(0) ' file size placeholder writer.Write(Encoding.ASCII.GetBytes("WAVE")) ' format ' fmt chunk writer.Write(Encoding.ASCII.GetBytes("fmt ")) ' chunk ID writer.Write(16) ' chunk size, 16 for PCM writer.Write(CUShort(1)) ' format: 1 = wave_format_pcm writer.Write(CUShort(1)) ' channel count writer.Write(cry.SampleRate) ' sample rate ' * 1 * 8 / 8 writer.Write(cry.SampleRate) ' SampleRate * NumChannels * BitsPerSample/8 ' * 8 / 8 writer.Write(CUShort(1)) ' NumChannels * BitsPerSample/8 writer.Write(CUShort(8)) ' bits per sample ' data chunk writer.Write(Encoding.ASCII.GetBytes("data")) ' chunk ID writer.Write(cry.Data.Length) ' chunk size For Each sample As SByte In cry.Data writer.Write(CByte(sample + &H80)) Next ' wave PCM is unsigned unlike GBA PCM which is ' fix header writer.Seek(4, SeekOrigin.Begin) writer.Write(CInt(writer.BaseStream.Length) - 8) End Using End Sub Public Function ImportCry(filename As String, CryToLoad As Cry) As Cry 'If Cry.Offset = 0 Then ' Return 'End If ' load a wave file Using reader = New BinaryReader(File.OpenRead(filename)) ' read RIFF header If reader.ReadUInt32() <> &H46464952 Then Throw New Exception("This is not a WAVE file!") End If If reader.ReadInt32() + 8 <> reader.BaseStream.Length Then Throw New Exception("Invalid file length!") End If If reader.ReadUInt32() <> &H45564157 Then Throw New Exception("This is not a WAVE file!") End If ' read fmt chunk If reader.ReadUInt32() <> &H20746D66 Then Throw New Exception("Expected fmt chunk!") End If If reader.ReadInt32() <> 16 Then Throw New Exception("Invalid fmt chunk!") End If If reader.ReadInt16() <> 1 Then ' only PCM format allowed Throw New Exception("Cry must be in PCM format!") End If If reader.ReadInt16() <> 1 Then ' only 1 channel allowed Throw New Exception("Cry cannot have more than one channel!") End If CryToLoad.SampleRate = reader.ReadInt32() If reader.ReadInt32() <> CryToLoad.SampleRate Then Throw New Exception("Invalid fmt chunk!") End If reader.ReadUInt16() Dim bitsPerSample = reader.ReadUInt16() If bitsPerSample <> 8 Then ' for now, only 8 bit PCM data Throw New Exception("Cries must be 8-bit WAVE files! Got {bitsPerSample}-bit instead.") End If ' data chunk If reader.ReadUInt32() <> &H61746164 Then Throw New Exception("Expected data chunk!!") End If Dim dataSize = reader.ReadInt32() CryToLoad.Data = New SByte(dataSize - 1) {} For i As Integer = 0 To dataSize - 1 ' read 8-bit unsigned PCM and convert to GBA signed form CryToLoad.Data(i) = CSByte(reader.ReadByte() - 128) Next End Using ' resetting some other properties just in case CryToLoad.Looped = False CryToLoad.LoopStart = 0 Return CryToLoad End Function 'Public Function SaveCry(crytosave As Cry, cryTable As Integer) As Boolean ' If crytosave.Offset = 0 Then ' Return False ' End If ' 'var lookup = new byte[] { 0x0, 0x1, 0x4, 0x9, 0x10, 0x19, 0x24, 0x31, 0xC0, 0xCF, 0xDC, 0xE7, 0xF0, 0xF7, 0xFC, 0xFF }; ' Dim lookup = New SByte() {0, 1, 4, 9, 16, 25, ' 36, 49, -64, -49, -36, -25, ' -16, -9, -4, -1} ' crytosave.Compressed = Pokemonedit.chkCompressed1.Checked ' ' copy cry data to be written ' Dim data = New List(Of Byte)() ' If crytosave.Compressed Then ' 'MsgBox("This should not be enabled!") ' 'End ' ' data is compressed in blocks of 1 + 0x20 bytes at a time ' ' first byte is normal signed PCM data ' ' following 0x20 bytes are compressed based on previous value ' ' (for a value not in lookup table, closest value will be chosen instead) ' 'Console.WriteLine("compressed"); ' ' each block has 0x40 samples ' Dim blockCount = crytosave.Data.Length / &H40 ' If crytosave.Data.Length Mod &H40 > 0 Then ' blockCount += 1 ' End If ' ' truncates the length of the last block ' ' so we don't waste space ' Dim lastBlockSize = crytosave.Data.Length - crytosave.Data.Length / &H40 * &H40 ' If lastBlockSize = 0 Then ' lastBlockSize = &H21 ' Else ' lastBlockSize = 1 + (lastBlockSize / 2) + (If(lastBlockSize Mod 2 = 0, 0, 1)) ' End If ' Dim blocks = New Byte(blockCount - 1)() {} ' For n As Integer = 0 To blockCount - 1 ' ' create new block ' If n < blockCount - 1 Then ' blocks(n) = New Byte(32) {} ' Else ' blocks(n) = New Byte(lastBlockSize - 1) {} ' End If ' Dim i As Integer = n * &H40 ' Dim k As Integer = 0 ' If i < crytosave.Data.Length Then ' ' set first value ' blocks(n)(k) = BitConverter.GetBytes(crytosave.Data(i))(0) ' End If ' k = k + 1 ' Dim pcm As SByte ' If i < crytosave.Data.Length Then ' pcm = crytosave.Data(i) ' End If ' i = i + 1 ' Dim j As Integer = 1 ' While j < &H40 And i < crytosave.Data.Length ' ' get current sample ' Dim sample As SByte = crytosave.Data(i) ' i = i + 1 ' ' difference between previous sample and this ' Dim diff As Integer = sample - pcm ' ' check for a perfect match in lookup table ' Dim lookupI = -1 ' For x As Integer = 0 To 15 ' If lookup(x) = diff And (pcm + diff <= 127) And (pcm + diff >= -128) Then ' lookupI = x ' Exit For ' End If ' Next ' ' search for the closest match in the table ' If lookupI = -1 Then ' Dim bestDiff As Integer = 255 ' For x As Integer = 0 To 15 ' If Math.Abs(CInt(lookup(x)) - diff) < bestDiff And (pcm + lookup(x) <= 127) And (pcm + lookup(x) >= -128) Then ' lookupI = x ' bestDiff = Math.Abs(lookup(x) - diff) ' End If ' Next ' End If ' ' set value in block ' ' on an odd value, increase position in block ' If j Mod 2 = 0 Then ' blocks(n)(k) = blocks(n)(k) Or CByte(lookupI << 4) ' Else ' blocks(n)(k) = blocks(n)(k) Or CByte(lookupI) ' k = k + 1 ' End If ' ' set previous ' pcm = sample ' j += 1 ' End While ' Next ' For n As Integer = 0 To blockCount - 1 ' data.AddRange(blocks(n)) ' Next ' Else ' ' uncompressed, copy directly to data ' 'Console.WriteLine("uncompressed"); ' For Each s As SByte In crytosave.Data ' data.Add(CByte(s And &HFF)) ' Next ' End If ' ' determine if cry requires repointing ' If crytosave.Size < data.Count Then ' Dim result As DialogResult = MessageBox.Show("The Cry will be written to free space and the pointer will be repointed. Would you like to do that?", ' "Repoint?", ' MessageBoxButtons.YesNo) ' If (result = DialogResult.Yes) Then ' Dim result2 As DialogResult = MessageBox.Show("Fill the old cry with free space?", ' "Delete old cry?", ' MessageBoxButtons.YesNo) ' If (result2 = DialogResult.Yes) Then ' WriteHEX(LoadedROM, crytosave.Offset, MakeFreeSpaceString(crytosave.Size + 16)) ' End If ' ' set new cry offset ' crytosave.Offset = SearchFreeSpaceFourAligned(LoadedROM, &HFF, data.Count, "&H" & GetString(GetINIFileLocation(), header, "StartSearchingForSpaceOffset", "800000")) ' Else ' Return False ' End If ' End If ' ' write cry ' WriteHEX(LoadedROM, crytosave.Offset, ReverseHEX(VB.Right("0000" & CUShort(If(crytosave.Compressed, 1, 0)), 4))) ' WriteHEX(LoadedROM, crytosave.Offset + 2, ReverseHEX(VB.Right("0000" & CUShort(If(crytosave.Looped, &H4000, 0)), 4))) ' WriteHEX(LoadedROM, crytosave.Offset + 4, ReverseHEX(VB.Right("00000000" & (crytosave.SampleRate << 10), 8))) ' WriteHEX(LoadedROM, crytosave.Offset + 8, ReverseHEX(VB.Right("00000000" & (crytosave.LoopStart), 8))) ' WriteHEX(LoadedROM, crytosave.Offset + 12, ReverseHEX(VB.Right("00000000" & (crytosave.Data.Length - 1), 8))) ' 'WriteHEX(LoadedROM, crytosave.Offset, ReverseHEX(VB.Right("0000" & CUShort(If(crytosave.Compressed, 1, 0)), 4))) ' 'WriteHEX(LoadedROM, crytosave.Offset + 2, ReverseHEX(VB.Right("0000" & CUShort(If(crytosave.Looped, &H4000, 0)), 4))) ' 'WriteHEX(LoadedROM, crytosave.Offset + 4, ReverseHEX(VB.Right("00000000" & (crytosave.SampleRate << 10), 8))) ' 'WriteHEX(LoadedROM, crytosave.Offset + 8, ReverseHEX(VB.Right("00000000" & (crytosave.LoopStart), 8))) ' 'WriteHEX(LoadedROM, crytosave.Offset + 12, ReverseHEX(VB.Right("00000000" & (crytosave.Data.Length - 1), 8))) ' Dim tempbuff As String = ByteArrayToHexString(data.ToArray) ' WriteHEX(LoadedROM, crytosave.Offset + 16, tempbuff) ' ' write cry table entry ' 'WriteHEX(LoadedROM, cryTable + (crytosave.Index * 12), ReverseHEX(If(crytosave.Compressed, "00003C20", "00003C00"))) ' 'WriteHEX(LoadedROM, cryTable + (crytosave.Index * 12) + 4, ReverseHEX(VB.Right("00000000" & Hex(crytosave.Offset), 8))) ' 'WriteHEX(LoadedROM, cryTable + (crytosave.Index * 12) + 8, "FF00FF") ' 'rom.WriteUInt16(CUShort(If(Cry.Compressed, 1, 0))) ' 'rom.WriteUInt16(CUShort(If(Cry.Looped, &H4000, 0))) ' 'rom.WriteInt32(Cry.SampleRate << 10) ' 'rom.WriteInt32(Cry.LoopStart) ' 'rom.WriteInt32(Cry.Data.Length - 1) ' 'rom.WriteBytes(data.ToArray()) ' '' write cry table entry ' 'rom.Seek(cryTable + Cry.Index * 12) ' 'rom.WriteUInt32(If(Cry.Compressed, &H3C20UI, &H3C00UI)) ' 'rom.WritePointer(Cry.Offset) ' 'rom.WriteUInt32(&HFF00FFUI) ' '' write growl table entry ' 'rom.Seek(growlTable + Cry.Index * 12) ' 'rom.WriteUInt32(If(Cry.Compressed, &H3C30UI, &H3C00UI)) ' '' !!! not sure if 00 should be used for uncompressed ' 'rom.WritePointer(Cry.Offset) ' 'rom.WriteUInt32(&HFF00FFUI) ' Return True 'End Function Public Function SaveCryNoPrompt(crytosave As Cry, cryTable As Integer, growlTable As Integer) As Boolean 'If crytosave.Offset = 0 Then 'Return False 'End If 'var lookup = new byte[] { 0x0, 0x1, 0x4, 0x9, 0x10, 0x19, 0x24, 0x31, 0xC0, 0xCF, 0xDC, 0xE7, 0xF0, 0xF7, 0xFC, 0xFF }; Dim lookup = New SByte() {0, 1, 4, 9, 16, 25, 36, 49, -64, -49, -36, -25, -16, -9, -4, -1} crytosave.Compressed = Pokemonedit.imptCompChk.Checked ' copy cry data to be written Dim data = New List(Of Byte)() If crytosave.Compressed Then 'MsgBox("This should not be enabled!") 'End ' data is compressed in blocks of 1 + 0x20 bytes at a time ' first byte is normal signed PCM data ' following 0x20 bytes are compressed based on previous value ' (for a value not in lookup table, closest value will be chosen instead) 'Console.WriteLine("compressed"); ' each block has 0x40 samples Dim blockCount = crytosave.Data.Length / &H40 If crytosave.Data.Length Mod &H40 > 0 Then blockCount += 1 End If ' truncates the length of the last block ' so we don't waste space Dim lastBlockSize = crytosave.Data.Length - crytosave.Data.Length / &H40 * &H40 If lastBlockSize = 0 Then lastBlockSize = &H21 Else lastBlockSize = 1 + (lastBlockSize / 2) + (If(lastBlockSize Mod 2 = 0, 0, 1)) End If Dim blocks = New Byte(blockCount - 1)() {} For n As Integer = 0 To blockCount - 1 ' create new block If n < blockCount - 1 Then blocks(n) = New Byte(32) {} Else blocks(n) = New Byte(lastBlockSize - 1) {} ' - Not "- 1" End If Dim i As Integer = n * &H40 Dim k As Integer = 0 If i < crytosave.Data.Length Then ' set first value blocks(n)(k) = BitConverter.GetBytes(crytosave.Data(i))(0) End If k = k + 1 Dim pcm As SByte If i < crytosave.Data.Length Then pcm = crytosave.Data(i) End If i = i + 1 Dim j As Integer = 1 While j < &H40 And i < crytosave.Data.Length ' get current sample Dim sample As SByte = crytosave.Data(i) i = i + 1 ' difference between previous sample and this Dim diff As Integer = Int16.Parse(sample) - Int16.Parse(pcm) Dim lookupI = -1 ' search for the closest match in the table Dim bestDiff As Integer = 255 For x As Integer = 0 To 15 'If ((Math.Abs(CInt(lookup(x)) - diff) < bestDiff) Or (lookup(x) = diff)) And Not ((lookup(x) < 0 And diff > 0) Or (lookup(x) > 0 And diff < 0)) Then ' Good or Perfect Difference If ((Math.Abs(CInt(lookup(x)) - diff) < bestDiff) Or (lookup(x) = diff)) Then ' Good or Perfect Difference 'Check for Overflow/Underflow to prevent crackling If (Int16.Parse(pcm) + lookup(x) < 127) Then If (Int16.Parse(pcm) + lookup(x) > -128) Then lookupI = x bestDiff = Math.Abs(lookup(x) - diff) Else End If Else End If End If Next ' set value in block ' on an odd value, increase position in block If j Mod 2 = 0 Then blocks(n)(k) = blocks(n)(k) Or CByte(lookupI << 4) Else blocks(n)(k) = blocks(n)(k) Or CByte(lookupI) k = k + 1 End If ' set previous pcm = pcm + lookup(lookupI) j += 1 End While Next For n As Integer = 0 To blockCount - 1 data.AddRange(blocks(n)) Next Else ' uncompressed, copy directly to data 'Console.WriteLine("uncompressed"); For Each s As SByte In crytosave.Data data.Add(CByte(s And &HFF)) Next End If ' set new cry offset crytosave.Offset = SearchFreeSpaceFourAligned(LoadedROM, &HFF, data.Count + 16, "&H" & GetString(GetINIFileLocation(), header, "StartSearchingForSpaceOffset", "800000")) ' write cry WriteHEX(LoadedROM, crytosave.Offset, ReverseHEX(VB.Right("0000" & CUShort(If(crytosave.Compressed, 1, 0)), 4))) WriteHEX(LoadedROM, crytosave.Offset + 2, ReverseHEX(VB.Right("0000" & CUShort(If(crytosave.Looped, &H4000, 0)), 4))) WriteHEX(LoadedROM, crytosave.Offset + 4, ReverseHEX(VB.Right("00000000" & Hex(crytosave.SampleRate << 10), 8))) WriteHEX(LoadedROM, crytosave.Offset + 8, ReverseHEX(VB.Right("00000000" & Hex(crytosave.LoopStart), 8))) WriteHEX(LoadedROM, crytosave.Offset + 12, ReverseHEX(VB.Right("00000000" & Hex(crytosave.Data.Length - 1), 8))) Dim tempbuff As String = ByteArrayToHexString(data.ToArray) WriteHEX(LoadedROM, crytosave.Offset + 16, tempbuff) ' write cry table entry WriteHEX(LoadedROM, cryTable + ((crytosave.Index - 1) * 12), ReverseHEX(If(crytosave.Compressed, "00003C20", "00003C00"))) WriteHEX(LoadedROM, cryTable + ((crytosave.Index - 1) * 12) + 4, ReverseHEX(VB.Right("00000000" & Hex(crytosave.Offset + &H8000000), 8))) WriteHEX(LoadedROM, cryTable + ((crytosave.Index - 1) * 12) + 8, "FF00FF") WriteHEX(LoadedROM, growlTable + ((crytosave.Index - 1) * 12), ReverseHEX(If(crytosave.Compressed, "00003C30", "00003C00"))) WriteHEX(LoadedROM, growlTable + ((crytosave.Index - 1) * 12) + 4, ReverseHEX(VB.Right("00000000" & Hex(crytosave.Offset + &H8000000), 8))) WriteHEX(LoadedROM, growlTable + ((crytosave.Index - 1) * 12) + 8, "FF00FF") If crytosave.Index > 276 Then Dim offset As Integer = Int32.Parse((GetString(GetINIFileLocation(), header, "CryConversionTable", "")), System.Globalization.NumberStyles.HexNumber) WriteHEX(LoadedROM, ((offset)) + ((crytosave.Index - 277) * 2), ReverseHEX(VB.Right("0000" & Hex(crytosave.Index - 1), 4))) End If Return True End Function End Module