diff --git a/Assets/Script/Data/SongInfo.Sources.cs b/Assets/Script/Data/SongInfo.Sources.cs index adbcecb66..1797b4fd8 100644 --- a/Assets/Script/Data/SongInfo.Sources.cs +++ b/Assets/Script/Data/SongInfo.Sources.cs @@ -43,7 +43,7 @@ public partial class SongInfo { { "tbrbdlc", "The Beatles: Rock Band DLC" }, { "tbrbcdlc", "The Beatles: Rock Band Custom DLC Project" }, { "rbacdc", "AC/DC Live: Rock Band Track Pack" }, - { "lrb", "Lego Rock Band" }, + { "lego", "Lego Rock Band" }, { "rbn", "Rock Band Network" }, { "ugc", "Rock Band Network 1.0" }, { "ugc_plus", "Rock Band Network 2.0" }, diff --git a/Assets/Script/Serialization/Xbox/XboxMoggData.cs b/Assets/Script/Serialization/Xbox/XboxMoggData.cs index 2c92f3847..2c9a8ef72 100644 --- a/Assets/Script/Serialization/Xbox/XboxMoggData.cs +++ b/Assets/Script/Serialization/Xbox/XboxMoggData.cs @@ -21,7 +21,7 @@ public class XboxMoggData { public int Header { get; set; } private uint MoggSize = 0; - private uint[] MoggOffsets = null; + private uint[] MoggOffsets = null; private bool isFromCON = false; public int MoggAddressAudioOffset { get; set; } @@ -40,7 +40,7 @@ public XboxMoggData(string str) { MoggPath = str; } - public XboxMoggData(string str, uint size, uint[] offsets){ + public XboxMoggData(string str, uint size, uint[] offsets) { MoggPath = str; MoggSize = size; MoggOffsets = offsets; @@ -50,19 +50,19 @@ public XboxMoggData(string str, uint size, uint[] offsets){ public void ParseMoggHeader() { using var fs = new FileStream(MoggPath, FileMode.Open, FileAccess.Read); using var br = new BinaryReader(fs); - if(isFromCON) fs.Seek(MoggOffsets[0], SeekOrigin.Begin); - + if (isFromCON) fs.Seek(MoggOffsets[0], SeekOrigin.Begin); + Header = br.ReadInt32(); MoggAddressAudioOffset = br.ReadInt32(); - if(isFromCON) MoggAudioLength = MoggSize - MoggAddressAudioOffset; + if (isFromCON) MoggAudioLength = MoggSize - MoggAddressAudioOffset; else MoggAudioLength = fs.Length - MoggAddressAudioOffset; } - public byte[] GetOggDataFromMogg(){ - if(!isFromCON) //Raw + public byte[] GetOggDataFromMogg() { + if (!isFromCON) //Raw return File.ReadAllBytes(MoggPath)[MoggAddressAudioOffset..]; - else{ //CON + else { //CON byte[] f = new byte[MoggSize]; uint lastSize = MoggSize % 0x1000; @@ -71,9 +71,9 @@ public byte[] GetOggDataFromMogg(){ using var fs = new FileStream(MoggPath, FileMode.Open, FileAccess.Read); using var br = new BinaryReader(fs, new ASCIIEncoding()); fs.Seek(MoggOffsets[i], SeekOrigin.Begin); - Array.Copy(br.ReadBytes((int)readLen), 0, f, i*0x1000, (int)readLen); + Array.Copy(br.ReadBytes((int) readLen), 0, f, i * 0x1000, (int) readLen); }); - + return f[MoggAddressAudioOffset..]; } } diff --git a/Assets/Script/Serialization/Xbox/XboxRawfileBrowser.cs b/Assets/Script/Serialization/Xbox/XboxRawfileBrowser.cs index 59dd802f7..b90d242d1 100644 --- a/Assets/Script/Serialization/Xbox/XboxRawfileBrowser.cs +++ b/Assets/Script/Serialization/Xbox/XboxRawfileBrowser.cs @@ -8,9 +8,10 @@ namespace YARG.Serialization { public static class XboxRawfileBrowser { - public static List BrowseFolder(string folder) { + public static List BrowseFolder(string folder, string folder_update) { var songList = new List(); var dtaTree = new DataArray(); + var dtaUpdate = new DataArray(); // Attempt to read songs.dta try { @@ -24,11 +25,33 @@ public static List BrowseFolder(string folder) { return null; } + // Attempt to read songs_updates.dta, if update folder was provided + if(folder_update != null){ + try { + using var sr = new StreamReader(Path.Combine(folder_update, "songs_updates.dta"), Encoding.GetEncoding("iso-8859-1")); + dtaUpdate = DTX.FromDtaString(sr.ReadToEnd()); + + Debug.Log("Successfully read update dta"); + } catch (Exception ee) { + Debug.LogError($"Failed to parse songs_updates.dta for `{folder_update}`."); + Debug.LogException(ee); + return null; + } + } + // Read each song the dta file lists for (int i = 0; i < dtaTree.Count; i++) { try { var currentArray = (DataArray) dtaTree[i]; var currentSong = new XboxSong(folder, currentArray); + + // if updates were provided + if(folder_update != null){ + // if dtaUpdate has the matching shortname, update that XboxSong + if(dtaUpdate.Array(currentSong.ShortName) is DataArray dtaMissing){ + currentSong.UpdateSong(folder_update, dtaMissing); + } + } if (currentSong.IsValidSong()) { songList.Add(currentSong); @@ -43,5 +66,28 @@ public static List BrowseFolder(string folder) { return songList; } + + public static void BrowseUpdateFolder(string folder, List baseSongs){ + var dtaTree = new DataArray(); + + // Attempt to read songs_updates.dta + try { + using var sr = new StreamReader(Path.Combine(folder, "songs_updates.dta"), Encoding.GetEncoding("iso-8859-1")); + dtaTree = DTX.FromDtaString(sr.ReadToEnd()); + + Debug.Log("Successfully read update dta"); + } catch (Exception e) { + Debug.LogError($"Failed to parse songs_updates.dta for `{folder}`."); + Debug.LogException(e); + return; + } + + // Read each song the update dta lists + for(int i = 0; i < dtaTree.Count; i++){ + Debug.Log(dtaTree[i].Name); + // if(baseSongs.ShortName) + } + } + } } \ No newline at end of file diff --git a/Assets/Script/Serialization/Xbox/XboxSong.cs b/Assets/Script/Serialization/Xbox/XboxSong.cs index 5f69f736e..c11f25010 100644 --- a/Assets/Script/Serialization/Xbox/XboxSong.cs +++ b/Assets/Script/Serialization/Xbox/XboxSong.cs @@ -8,6 +8,7 @@ namespace YARG.Serialization { public class XboxSong { public string ShortName { get; private set; } public string MidiFile { get; private set; } + public string MidiUpdateFile { get; private set; } private string songFolderPath; @@ -42,6 +43,37 @@ public XboxSong(string pathName, DataArray dta) { } } + public void UpdateSong(string pathUpdateName, DataArray dta_update){ + songDta.ParseFromDta(dta_update); + // if dta_update.Array("song") is not null, parse for any MoggDta as well + if(dta_update.Array("song") is DataArray moggUpdateDta) + moggDta.ParseFromDta(moggUpdateDta); + + // if extra_authoring has disc_update, grab update midi + if(songDta.discUpdate){ + MidiUpdateFile = Path.Combine(pathUpdateName, ShortName, $"{ShortName}_update.mid"); + } + + // if update mogg exists, grab it and parse it + string moggUpdatePath = Path.Combine(pathUpdateName, ShortName, $"{ShortName}_update.mogg"); + if(File.Exists(moggUpdatePath)){ + moggDta.UpdateMoggPath(moggUpdatePath); + moggDta.ParseMoggHeader(); + // moggDta.ParseFromDta(dta_update.Array("song")); + moggDta.CalculateMoggBassInfo(); + } + + // if album_art == TRUE AND alternate_path == TRUE, grab update png + if(songDta.albumArt && songDta.alternatePath){ + Debug.Log($"new album art, grabbing it now"); + // make a new image here, cuz what if an old one exists? + img = new XboxImage(Path.Combine(pathUpdateName, ShortName, "gen", $"{ShortName}_keep.png_xbox")); + + // Do some preliminary parsing here in the header to get DXT format, width and height, etc + img.ParseImageHeader(); + } + } + public bool IsValidSong() { // Skip if the song doesn't have notes if (!File.Exists(MidiFile)) { diff --git a/Assets/Script/Serialization/Xbox/XboxSongData.cs b/Assets/Script/Serialization/Xbox/XboxSongData.cs index afee98dfa..7395e99bb 100644 --- a/Assets/Script/Serialization/Xbox/XboxSongData.cs +++ b/Assets/Script/Serialization/Xbox/XboxSongData.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using DtxCS.DataTypes; +using UnityEngine; // complete GH DX songs.dta additions: // artist (songalbum, author (as in chart author), songyear, songgenre, songorigin, @@ -27,6 +28,8 @@ public class XboxSongData { public byte? albumTrackNumber; public byte vocalParts = 1; public bool fake = false; + public bool alternatePath = false; + public bool discUpdate = false; public (uint start, uint end) preview; public short[] realGuitarTuning, realBassTuning; public string[] solos; @@ -124,6 +127,28 @@ public void ParseFromDta(DataArray dta) { realBassTuning = new short[4]; for (int b = 0; b < 4; b++) realBassTuning[b] = (short) ((DataAtom) bassTunes[b]).Int; break; + case "alternate_path": + if (dtaArray[1] is DataSymbol symAltPath) + alternatePath = (symAltPath.Name.ToUpper() == "TRUE"); + else if (dtaArray[1] is DataAtom atmAltPath) + alternatePath = (atmAltPath.Int != 0); + break; + case "extra_authoring": + for(int ea = 1; ea < dtaArray.Count; ea++){ + if(dtaArray[ea] is DataSymbol symEA){ + if(symEA.Name == "disc_update"){ + discUpdate = true; + break; + } + } + else if(dtaArray[ea] is DataAtom atmEA){ + if(atmEA.String == "disc_update"){ + discUpdate = true; + break; + } + } + } + break; case "quickplay": //used in GH for (int q = 1; q < dtaArray.Count; q++) { DataArray innerQPArray = (DataArray) dtaArray[q]; diff --git a/Assets/Script/SongLibrary.cs b/Assets/Script/SongLibrary.cs index 028d5aaaa..a2c6de35c 100644 --- a/Assets/Script/SongLibrary.cs +++ b/Assets/Script/SongLibrary.cs @@ -289,7 +289,9 @@ private static void ReadSongInfo() { // Rock Band CON rawfiles // Read all of the songs in the file - var files = XboxRawfileBrowser.BrowseFolder(info.path); + // Apply any song updates, if they exist + // Debug.Log($"song path root: {info.root}"); + var files = XboxRawfileBrowser.BrowseFolder(info.path, Path.Combine(info.root, "songs_updates")); // Convert each to a SongInfo foreach (var file in files) {