Example #1
0
        public PakEditor(PakFormat pakFormat, bool debugFile)
        {
            if (pakFormat.PakFilename == null || pakFormat.PakFilename == string.Empty)
                throw new ArgumentException("There is no PakFileName in the pakFormat argument");

            parsePak(pakFormat, debugFile);
        }
Example #2
0
 /// <summary>
 /// Open using a stream, filename is just for reference. The stream must start with the file (the position is depended on)
 /// </summary>
 /// <param name="filename"></param>
 /// <param name="stream"></param>
 public QbFile(string filename, string debugFileContents, Stream stream, PakFormat pakFormat)
 {
     _pakFormat = pakFormat;
     _filename  = filename;
     loadDebugFile(debugFileContents);
     parse(stream);
 }
Example #3
0
        /// <summary>
        /// Create a blank QbFile
        /// </summary>
        internal QbFile(string qbFilename, PakFormat pakFormat, uint magic, byte[] unknownData)
        {
            _pakFormat = pakFormat;
            _filename  = qbFilename;
            _magic     = magic;
            _items     = new List <QbItemBase>();

            _items.Add(new QbItemUnknown(unknownData, 0, this));
        }
Example #4
0
        public PakEditor(PakFormat pakFormat, bool debugFile)
        {
            if (pakFormat.PakFilename == null || pakFormat.PakFilename == string.Empty)
            {
                throw new ArgumentException("There is no PakFileName in the pakFormat argument");
            }



            parsePak(pakFormat, debugFile);
        }
Example #5
0
        public QbFile(string filename, string debugFilename, PakFormat pakFormat)
        {
            _pakFormat = pakFormat;
            _filename  = filename;

            if (debugFilename.Length != 0 && File.Exists(debugFilename))
            {
                loadDebugFile(File.ReadAllText(debugFilename));
            }

            using (FileStream fs = File.Open(_filename, FileMode.Open, FileAccess.Read))
                parse(fs);
        }
Example #6
0
        internal FileManager(Project project, IPluginFileCopy fileCopyPlugin, string gameLocation)
        {
            _pakFormat = null;
            _pakEditor = null;
            _dbgEditor = null;

            _songListQbFile = null;
            _guitarProgressionQbFile = null;

            _project = project;
            _files = new Dictionary<string, GameFile>();
            _fileCopy = fileCopyPlugin;
            _gameLocation = gameLocation;
            _backgroundAudioDatWad = null;
        }
Example #7
0
        private void replaceDataPartition(int songsToAdd, bool addNonCareerToBonus, bool removeBossBattles, int bonusSongs, int[] tierSongs)
        {
            //#if (!DEBUG)
            ///////////////////////////////////////////////////////////
            //  SHRINK UPDATE PARTITION
            ///////////////////////////////////////////////////////////
                lblStatus.Text = "Shrinking Update Partition...";
            lblStatus.Update();

            if (_prepProps.RemoveUpdatePartition != YesNo.Yes)
                replaceUpdatePartition(false);

            prgInc(_shrinkPrgSize);

            ///////////////////////////////////////////////////////////
            //  EXTRACT PARTITION
            ///////////////////////////////////////////////////////////
            lblStatus.Text = "Extracting Data Partition...";
            lblStatus.Update();
            //#endif
            DirectoryInfo pt = new DirectoryInfo(string.Format(@"{0}\PartitionData", _project.WorkingPath.TrimEnd('\\')));

            //#if (!DEBUG)
            int i = 5; //try 5 times
            bool er = true;
            if (pt.Exists)
            {
                do
                {
                    try
                    {
                        pt.Delete(true);
                        er = false;
                    }
                    catch
                    {
                        er = true;
                        System.Threading.Thread.Sleep(100);
                        if (--i == 0)
                            throw;
                    }
                } while (er == true);

            }
            pt.Create();

            ExtractPartition(_project.SourcePath, _partitionNo, pt.FullName);
            prgInc(_shrinkPrgSize);
            //#endif
            ///////////////////////////////////////////////////////////
            //  EDIT FILES
            ///////////////////////////////////////////////////////////
            lblStatus.Text = "Editing Files...";
            lblStatus.Update();

            prepMovies(new DirectoryInfo(string.Format(@"{0}\movies", pt.FullName)));

            prepRemoveFiles(pt);

            if (_prepProps.EnableTierEditing == YesNo.Yes || songsToAdd != 0 || _prepProps.AddNonCareerTracksToBonus == YesNo.Yes)
                _project.GameMods.AddSongs(pt, songsToAdd, rdbGameGh3.Checked ? "lagrange" : "dreampolice", addNonCareerToBonus, new DirectoryInfo(_project.WorkingPath));

            PakFormat pf = new PakFormat(string.Format(@"{0}\pak\{1}", pt.FullName, _project.FileManager.PakFormat.PakFilename), string.Empty, string.Empty, PakFormatType.Wii, false);
            PakEditor pe = new PakEditor(pf, false);

            if (_prepProps.EnableTierEditing == YesNo.Yes && (removeBossBattles || tierSongs != null))
                _project.GameMods.EditTiers(pe, removeBossBattles, _prepProps.Tiers, bonusSongs, tierSongs, _prepProps.UnlockSetlistTiers == YesNo.Yes);

            if (_prepProps.SetCheats == YesNo.Yes)
                _project.GameMods.SetCheats(pe);

            if (_prepProps.RemoveIntroVideos == YesNo.Yes)
                _project.GameMods.RemoveIntroVids(pe);

            if (_prepProps.FreeStore == YesNo.Yes)
                _project.GameMods.FreeStore(pe);

            if (_prepProps.DefaultBonusSongArt == YesNo.Yes)
                _project.GameMods.ResetBonusArt(pe);

            if (_prepProps.DefaultBonusSongInfo == YesNo.Yes)
                _project.GameMods.ResetBonusInfoText(pe, _prepProps.DefaultBonusSongInfoText);

            //perform this step after edit tiers as edit tiers set the unlock values
            if (_prepProps.UnlockSetlistTiers == YesNo.Yes || _prepProps.CompleteTier1Song == YesNo.Yes)
                _project.GameMods.UnlockSetlists(pe, _prepProps.UnlockSetlistTiers == YesNo.Yes, _prepProps.CompleteTier1Song == YesNo.Yes);

            prgInc(_shrinkPrgSize);

            if (_prepProps.ManualEditing == YesNo.Yes)
            {
                lblStatus.Text = "Manual Editing...";
                lblStatus.Update();

                if (MessageBox.Show(this, string.Format("Edit the partition files here: {0}{1}{1}You can use TheGHOST with the File System plugin at this point to replace songs, or make manual adjustments.{1}{1}Press OK to build the partition and insert it into the ISO.", pt.FullName, Environment.NewLine), "Continue", MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.Cancel)
                    return;
            }

            Application.DoEvents();
            int songNo = 0;

            DirectoryInfo ghostDir = new DirectoryInfo(string.Format(@"{0}\-TheGHOST-", pt.FullName));
            string fileName = string.Format(@"{0}\info.txt", ghostDir.FullName);

            if (ghostDir.Exists)
            {
                if (File.Exists(fileName))
                {
                    string[] txt = File.ReadAllLines(fileName);
                    if (txt.Length > 1)
                    {
                        if (txt[1].StartsWith("TheGHOSTSongs="))
                            songNo = int.Parse(txt[1].Split('=')[1]);
                    }
                }
            }
            else
                ghostDir.Create();

            //don't save the count of songs added with TheGHOST anymore
            //if (_prepProps.AddSongsCount > songNo)
            //    songNo = _prepProps.AddSongsCount;

            string info = string.Format("{1} - v{2} / v{3}{0}TheGHOSTSongs={4}{0}", Environment.NewLine, TheGhostCore.AppName, TheGhostCore.AppVersion, TheGhostCore.CoreVersion, songNo.ToString());
            info = string.Concat(info, new string(' ', 1024 - info.Length));
            File.WriteAllText(fileName, info);

            ///////////////////////////////////////////////////////////
            //  MOVING PARTITION
            //////////////////////////////////////////////////////////
            //#if (!DEBUG)
            lblStatus.Text = "Moving Partition...";
            lblStatus.Update();

            ShufflePartitions(_project.SourcePath);
            prgInc(_shrinkPrgSize);
            //#endif
            ///////////////////////////////////////////////////////////
            //  BUILD PARTITION
            ///////////////////////////////////////////////////////////
            lblStatus.Text = "Building Partition...";
            lblStatus.Update();

            GameFile[] files = _project.FileManager.Import(GameFileType.Other, null,
                @"\partition.bin", @"\main.dol", @"\apploader.img", @"\bi2.bin", @"\boot.bin");

            FileInfo ptImg = new FileInfo(string.Format(@"{0}.img", pt.FullName));
            WiiIso.BuildPartition(files[0].LocalName, files[1].LocalName, files[2].LocalName, files[3].LocalName, files[4].LocalName,
                pt.FullName, ptImg.FullName, true);

            _project.FileManager.RemoveAndDeleteAllFiles();  //remove extracted files (partition.bin etc)

            prgInc(_shrinkPrgSize);

            ///////////////////////////////////////////////////////////
            //  REPLACE PARTITION
            //////////////////////////////////////////////////////////
            lblStatus.Text = "Replacing Partition...";
            lblStatus.Update();

            LoadPartition(_project.SourcePath, ptImg.FullName, _partitionNo);
            FileHelper.Delete(ptImg.FullName);
            prgInc(_shrinkPrgSize);

            ///////////////////////////////////////////////////////////
            //  COMPLETE
            ///////////////////////////////////////////////////////////

            MaxPartition(_project.SourcePath, _partitionNo);

            //ISO IS LOCKED BY WIISCRUBBER
            //if (chkRenameIso.Checked)
            //{
            //    FileInfo iso = new FileInfo(_project.SourcePath);
            //    File.Move(iso.FullName, string.Format("{0}_prepped{1}", iso.Name.Substring(0, iso.Name.Length - iso.Extension.Length), iso.Extension));
            //}

            lblStatus.Text = "Complete, Backup this ISO and use a copy of it when replacing songs.";
            prg.Value = prg.Maximum;
        }
Example #8
0
 /// Open using a stream.
 public QbFile(Stream stream, PakFormat pakFormat)
     : this("", "", stream, pakFormat)
 {
 }
Example #9
0
        /// <summary>
        /// Create a blank QbFile
        /// </summary>
        internal QbFile(string qbFilename, PakFormat pakFormat, uint magic, byte[] unknownData)
        {
            _pakFormat = pakFormat;
            _filename = qbFilename;
            _magic = magic;
            _items = new List<QbItemBase>();

            _items.Add(new QbItemUnknown(unknownData, 0, this));
        }
Example #10
0
 /// <summary>
 /// Open using a stream, filename is just for reference. The stream must start with the file (the position is depended on)
 /// </summary>
 /// <param name="filename"></param>
 /// <param name="stream"></param>
 public QbFile(string filename, string debugFileContents, Stream stream, PakFormat pakFormat)
 {
     _pakFormat = pakFormat;
     _filename = filename;
     loadDebugFile(debugFileContents);
     parse(stream);
 }
Example #11
0
 /// Open using a stream.
 public QbFile(Stream stream, string debugFileContents, PakFormat pakFormat)
     : this("", debugFileContents, stream, pakFormat)
 {
 }
Example #12
0
        private bool _requiresPab; //PAB required

        #endregion Fields

        #region Constructors

        public PakEditor(PakFormat pakFormat)
            : this(pakFormat, false)
        {
        }
Example #13
0
        public QbFile(string filename, string debugFilename, PakFormat pakFormat)
        {
            _pakFormat = pakFormat;
            _filename = filename;

            if (debugFilename.Length != 0 && File.Exists(debugFilename))
                loadDebugFile(File.ReadAllText(debugFilename));

            using (FileStream fs = File.Open(_filename, FileMode.Open, FileAccess.Read))
                parse(fs);
        }
Example #14
0
        private void btnPakFile_Click(object sender, EventArgs e)
        {
            string file = getBestFullFilename(txtPakFile.Text);

            PakFormat pts = new PakFormat(file, "", "", formatToPakFormatType(cboFormatType.Text));
            openInput.Filter = string.Format("{0} (*.pak.{1})|*.pak.{1}|All files (*.*)|*.*", pts.PakFormatType.ToString(), pts.FileExtension);
            openInput.Title = string.Format("Open {0} PAK file", pts.PakFormatType.ToString());

            openInput.FileName = file;
            if (openInput.ShowDialog(this) != DialogResult.Cancel)
            {
                txtPakFile.Text = openInput.FileName;
                pts = new PakFormat(txtPakFile.Text, "", "", formatToPakFormatType(cboFormatType.Text));
                if (!pts.IsCompressed && pts.PabFileExists)
                    txtPabFile.Text = pts.FullPabFilename;
                else if (pts.IsCompressed && pts.CompressedPabFileExists)
                    txtPabFile.Text = pts.FullCompressedPabFilename;
                else
                    txtPabFile.Text = string.Empty;
                if (!pts.IsCompressed && pts.DebugFileExists)
                    txtDebugFile.Text = pts.FullDebugFilename;
                else if (pts.IsCompressed && pts.CompressedDebugFileExists)
                    txtDebugFile.Text = pts.FullCompressedDebugFilename;
                else
                    txtDebugFile.Text = string.Empty;
            }
        }
Example #15
0
        /// <summary>
        /// Add new songs to GH3, this method requires that the partition 2 files are on the local disc
        /// </summary>
        public void AddSongs(DirectoryInfo rootPartitionPath, int adjustBy, string sourceSong, bool addNonCareerSongs, DirectoryInfo workingPath)
        {
            PakFormat pf = new PakFormat(string.Format(@"{0}\pak\{1}", rootPartitionPath.FullName, _project.FileManager.PakFormat.PakFilename), string.Empty, string.Empty, PakFormatType.Wii, false);
            PakEditor pe = new PakEditor(pf, false);

            string songlistQb = @"scripts\guitar\songlist.qb.ngc";
            string storeDataQb = @"scripts\guitar\store_data.qb.ngc";
            string guitProgQb = @"scripts\guitar\guitar_progression.qb.ngc";

            if (_project.GameInfo.Game == Game.GH3_Wii)
            {
                songlistQb = songlistQb.Substring(1);  //remove first char
                storeDataQb = storeDataQb.Substring(1);  //remove first char
                guitProgQb = guitProgQb.Substring(1);  //remove first char
            }

            if (_project.GameInfo.Game == Game.GH3_Wii || _project.GameInfo.Game == Game.GHA_Wii)
            {
                //add song to song list
                QbFile qb = pe.ReadQbFile(songlistQb);
                QbFile qbStore = pe.ReadQbFile(storeDataQb);
                QbFile qbGuitProg = pe.ReadQbFile(guitProgQb);

                string silentXbox = createBlankSourceAudio(workingPath);

                QbItemArray songsList = qb.FindItem(QbKey.Create("gh3_songlist"), false) as QbItemArray;

                List<QbKey> careerSongs = getAllCareerSongs(qbGuitProg);
                List<QbKey> bonusSongs = getAllBonusSongs(qbStore);
                List<QbKey> allSongs = new List<QbKey>(careerSongs);
                allSongs.AddRange(bonusSongs);

                //remove the boss battles. If we pick new files from the career then they will be removed anyway
                //QbKey[] bossSongs = new QbKey[] { QbKey.Create("bosstom"), QbKey.Create("bossslash"), QbKey.Create("bossdevil"), QbKey.Create("bossjoe") };
                //foreach (QbKey qk in bossSongs)
                //    careerSongs.Remove(qk);

                //insert the special songs on the end (that aren't in the career)
                List<QbKey> specialSongs = new List<QbKey>();
                foreach (QbKey k in _specialSongs)
                {
                    if (!careerSongs.Contains(k))
                        specialSongs.Add(k);
                }

                if (adjustBy > 0)
                {
                    //Calculate extras
                    int add = adjustBy + (addNonCareerSongs ? _nonCareerSongs.Count : 0);

                    foreach (QbKey k in specialSongs)
                    {
                        if (!bonusSongs.Contains(k))
                        {
                            if (_project.GameInfo.Game == Game.GH3_Wii)
                                add--; //if bonus songs currently doesn't contian this special track then add one less song
                            else
                                add++; //GHA k&qcred will be added from not existing
                        }
                    }
                    add = Math.Max(0, add);

                    List<QbKey> newBonusList = new List<QbKey>();

                    //add the special songs on the end - DO THIS FIRST
                    foreach (QbKey k in specialSongs)
                    {
                        if (!careerSongs.Contains(k))
                            newBonusList.Add(k);
                    }

                    int specialAdded = newBonusList.Count;

                    //find the last _restoresong (a regular-song list in the correct order) in the career
                    int start = -1;
                    for (int i = careerSongs.Count - 1; i >= 0; i--)
                    {
                        start = _restoreSongs.IndexOf(careerSongs[i]);
                        if (start >= 0)
                            break;
                    }

                    if (start != -1)
                    {
                        start++; //move to the next item

                        for (int i = start; i < _restoreSongs.Count; i++)
                        {
                            if (newBonusList.Count >= add + bonusSongs.Count) //add + existing bonussongs = correct count
                                break;

                            if (!careerSongs.Contains(_restoreSongs[i]))
                                newBonusList.Insert(newBonusList.Count - specialAdded, _restoreSongs[i]);
                        }
                    }

                    //nonCareer songs (only on GH3)
                    if (addNonCareerSongs)
                    {
                        for (int i = 0; i < _nonCareerSongs.Count; i++)
                        {
                            if (newBonusList.Count >= add + bonusSongs.Count)
                                break;

                            if (!careerSongs.Contains(_nonCareerSongs[i]))
                                newBonusList.Insert(newBonusList.Count - specialAdded, _nonCareerSongs[i]);
                        }
                    }

                    //add ghost songs
                    int num = 1;
                    while (newBonusList.Count < add + bonusSongs.Count)
                    {
                        QbKey qk = QbKey.Create(string.Format("theghost{0}", (num++).ToString().PadLeft(3, '0')));

                        if (!careerSongs.Contains(qk))
                            newBonusList.Insert(newBonusList.Count - specialAdded, qk);
                    }

                    //remove any bonus songs not in our list
                    foreach (QbKey k in bonusSongs)
                    {
                        if (!newBonusList.Contains(k))
                        {
                            if (!careerSongs.Contains(k))
                                this.BonusSongRemoveFromGame(qbStore, qb, k); //remove from set list also
                            else
                                removeBonusSong(qbStore, k);
                        }
                    }

                    //add all the missing items to the bonus lists
                    foreach (QbKey k in newBonusList)
                    {
                        if (!bonusSongs.Contains(k))
                        {
                            this.BonusSongAddToGame(qbStore, qb, k.Clone(), false);
                            addBonusSongNotes(rootPartitionPath, QbKey.Create(sourceSong), k.Clone(), pe);
                            createBonusSongAudio(rootPartitionPath, silentXbox, k);
                        }
                    }

                    //set the correct order in the store list
                    //find bonus song list
                    QbItemArray qbBonusSongs = qbStore.FindItem(QbKey.Create("songs"), true) as QbItemArray;

                    //add bonus song to list
                    if (qbBonusSongs != null)
                        (qbBonusSongs.Items[0] as QbItemQbKey).Values = newBonusList.ToArray();

                    qbStore.AlignPointers();
                    qbStore.IsValid();
                    qb.AlignPointers();
                    qb.IsValid();

                }
                else if (adjustBy < 0)
                {
                    if (addNonCareerSongs) //adds kings and queens credits if required
                        this.AddBonusSongsFromNonCareer(qbStore, qb, qbGuitProg);

                    bonusSongs = getAllBonusSongs(qbStore);

                    //remove bonus songs that aren't required. keep any required
                    int offset = 0;
                    while (adjustBy != 0 && bonusSongs.Count > 0 && bonusSongs.Count - offset > 0)
                    {
                        int idx = (bonusSongs.Count - offset) - 1;

                        if (bonusSongs[idx].Crc == QbKey.Create("kingsandqueenscredits").Crc
                         || bonusSongs[idx].Crc == QbKey.Create("kingsandqueens").Crc
                         || bonusSongs[idx].Crc == QbKey.Create("thrufireandflames").Crc)
                        {
                            offset++;
                            continue;
                        }

                        if (!careerSongs.Contains(bonusSongs[idx]))
                            this.BonusSongRemoveFromGame(qbStore, qb, bonusSongs[idx]); //remove from set list also
                        else
                            removeBonusSong(qbStore, bonusSongs[idx]);
                        bonusSongs.RemoveAt(idx);
                        adjustBy++;
                    }
                }
                else if (adjustBy == 0 && addNonCareerSongs)
                {
                    this.AddBonusSongsFromNonCareer(qbStore, qb, qbGuitProg);
                }

                qb.AlignPointers();
                qb.IsValid();
                qbStore.AlignPointers();
                qbStore.IsValid();

                FileHelper.Delete(silentXbox);
                pe.ReplaceFile(songlistQb, qb);
                pe.ReplaceFile(storeDataQb, qbStore);
            }
        }
Example #16
0
        private void btnLoadPak_Click(object sender, EventArgs e)
        {
            try
            {
                this.Cursor = Cursors.WaitCursor;

                if (txtPakFile.Text.Trim().Length == 0)
                {
                    showError("Pak File Error", "The PAK filename is blank");
                    return;
                }

                _pakFormat = new PakFormat(txtPakFile.Text, txtPabFile.Text, txtDebugFile.Text, formatToPakFormatType(cboFormatType.Text), false);

                if (_pakFormat.IsCompressed)
                {
                    if (!_pakFormat.CompressedPakFileExists)
                    {
                        showError("Pak File Error", string.Format("The PAK file does not exist '{0}'", txtPakFile.Text));
                        return;
                    }

                    if (txtPabFile.Text.Length != 0 && !_pakFormat.CompressedPabFileExists)
                    {
                        showError("Pab File Error", string.Format("The PAB file does not exist '{0}'", txtPabFile.Text));
                        return;
                    }

                    if (txtDebugFile.Text.Length != 0 && !_pakFormat.CompressedDebugFileExists)
                    {
                        showError("Debug File Error", string.Format("The Debug file does not exist '{0}'", txtDebugFile.Text));
                        return;
                    }
                }
                else
                {
                    if (!_pakFormat.PakFileExists)
                    {
                        showError("Pak File Error", string.Format("The PAK file does not exist '{0}'", txtPakFile.Text));
                        return;
                    }

                    if (txtPabFile.Text.Length != 0 && !_pakFormat.PabFileExists)
                    {
                        showError("Pab File Error", string.Format("The PAB file does not exist '{0}'", txtPabFile.Text));
                        return;
                    }

                    if (txtDebugFile.Text.Length != 0 && !_pakFormat.DebugFileExists)
                    {
                        showError("Debug File Error", string.Format("The Debug file does not exist '{0}'", txtDebugFile.Text));
                        return;
                    }
                }

                clearInterface();

                AppState.InputFormat = cboFormatType.Text;
                AppState.PakFilename = txtPakFile.Text;
                AppState.PabFilename = txtPabFile.Text;
                AppState.DebugFilename = txtDebugFile.Text;
                AppState.Backup = chkBackup.Checked;

                try
                {
                    if (chkBackup.Checked)
                    {
                        if (_pakFormat.PakFormatType == PakFormatType.XBox)
                        {
                            backup(_pakFormat.FullCompressedPakFilename);
                            if (_pakFormat.PabFileExists)
                                backup(_pakFormat.FullCompressedPabFilename);
                        }
                        else
                        {
                            backup(_pakFormat.FullPakFilename);
                            if (_pakFormat.PabFileExists)
                                backup(_pakFormat.FullPabFilename);
                        }
                    }
                }
                catch (Exception ex)
                {
                    showException("PAK Backup Error", ex);
                    clearInterface();
                    return;
                }

                try
                {
                    _pakFile = new PakEditor(_pakFormat);
                }
                catch (Exception ex)
                {
                    showException("PAK File Load/Parse Error", ex);
                    clearInterface();
                    return;
                }

                if (_pakFile.RequiresPab && !_pakFormat.PabFileExists)
                {
                    showError("PAK Error", "The data for this PAK is not present, it may require a PAB");
                    clearInterface();
                    return;
                }

                try
                {
                    if (_pakFormat.DebugFileExists)
                        _dbgFile = new PakEditor(_pakFormat, true);
                    else
                        _dbgFile = null;
                }
                catch (Exception ex)
                {
                    showException("Debug File Load/Parse Error", ex);
                    clearInterface();
                    return;
                }

                try
                {
                    ListViewItem li;
                    string[] fn;
                    char[] sc = new char[] { '\\' };

                    lstPakContents.BeginUpdate();
                    lstPakContents.ListViewItemSorter = null;
                    lstPakContents.Items.Clear();
                    foreach (PakHeaderItem phi in _pakFile.Headers.Values)
                    {
                        fn = phi.Filename.Split(sc);
                        li = new ListViewItem(fn[fn.Length - 1]);
                        li.SubItems.Add(phi.Filename);
                        li.SubItems.Add(string.Format("{0} ({1})", (phi.HeaderStart + phi.FileOffset).ToString("X").PadLeft(8, '0'), (phi.HeaderStart + phi.FileOffset).ToString()));
                        li.SubItems.Add(phi.FileLength.ToString());
                        li.SubItems.Add(phi.FileType.Text);
                        li.ImageIndex = getPakFileImageIndex(phi.PakFileType);
                        li.Tag = phi;
                        lstPakContents.Items.Add(li);
                    }

                    lstPakContents.Focus();

                    updateStatusItems();
                }
                catch (Exception ex)
                {
                    showException("PAK List Population Error", ex);
                    clearInterface();
                    return;
                }
                finally
                {
                    lstPakContents.ListViewItemSorter = _lvwPakColumnSorter;
                    lstPakContents.EndUpdate();
                }

                lstPakContents.Sort();

                if (lstPakContents.Items.Count > 0)
                {
                    lstPakContents.Items[0].Selected = true;
                    lstPakContents.Items[0].Focused = true;
                }

                tabPak.Text = string.Format("PAK: {0}", (new FileInfo(_pakFile.Filename)).Name);
                mnuEditQBFile.Enabled = true;
            }
            finally
            {
                this.Cursor = Cursors.Default;

                try
                {
                    if (_pakFile.StructItemChildrenType == StructItemChildrenType.NotSet)
                    {
                        if (MessageBox.Show(this,
            @"Unable to detect StructItem Children Type.

            Is this a newer PAK file (GH:WT onwards)?

            New PAK files have array IDs within Struct types. Queen Bee can load these
            types without needing to know the type. It is required when creating new types
            This PAK has no StructItem children so this setting could not be detected.", "StructItem Children Type", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            _pakFormat.StructItemChildrenType = StructItemChildrenType.ArrayItems;
                        }
                        else
                        {
                            _pakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        }
                    }
                }
                catch
                {
                }
            }
        }
Example #17
0
        private void parsePak(PakFormat pakFormat, bool debugFile)
        {
            _debugFile = debugFile;
            _pakFormat = pakFormat;
            _pakFilename = (!_debugFile ? _pakFormat.FullPakFilename : _pakFormat.FullDebugFilename);

            Dictionary<uint, PakDbgQbKey> qbKeyFilenames = new Dictionary<uint, PakDbgQbKey>();

            //if PC or xbox then we need to look up the filename from the debug file
            //create a PakEditor and load the debug pak, then load all internal debug files, add the first line to our filenames dictionary
            if (!debugFile) // && (_pakFormat.PakFormatType == PakFormatType.PC || _pakFormat.PakFormatType == PakFormatType.XBox))
            {
                try
                {
                    _pakFormat.Decompress();
                    _pakFilename = _pakFormat.FullPakFilename;
                }
                catch (Exception ex)
                {
                    throw new Exception("Decompression Error", ex);
                }

                if (_pakFormat.DebugFileExists)
                {
                    string debugFileContents;
                    string filename;
                    uint crc;
                    PakEditor pakDebug = new PakEditor(new PakFormat(_pakFormat.FullDebugFilename, "", _pakFormat.FullDebugFilename, _pakFormat.PakFormatType), true);
                    foreach (PakHeaderItem dphi in pakDebug.Headers.Values)
                    {
                        debugFileContents = string.Empty;
                        filename = string.Empty;
                        crc = 0;
                        if (dphi.FullFilenameQbKey != 0)
                            crc = dphi.FullFilenameQbKey;
                        else if (dphi.PakFullFileNameQbKey != 0)
                            crc = dphi.PakFullFileNameQbKey;
                        else if (dphi.NameOnlyCrc != 0)
                            crc = dphi.NameOnlyCrc;

                        if (crc != 0)
                        {
                            filename = crc.ToString("X").PadLeft(8, '0');
                            if (pakDebug.Headers.ContainsKey(filename.ToLower()))
                            {
                                debugFileContents = pakDebug.ExtractFileToString(filename);

                                if (debugFileContents.Length != 0)
                                    addDebugFilename(debugFileContents, qbKeyFilenames, crc);
                            }
                        }
                    }
                }

            }

            long minOffset = uint.MaxValue;
            long maxOffset = 0;

            _pakHeaders = new Dictionary<string, PakHeaderItem>();

            using (Stream st = File.Open(_pakFilename, FileMode.Open, FileAccess.Read))
            {
                _pakFileLength = st.Length;

                using (BinaryEndianReader br = new BinaryEndianReader(st))
                {
                    PakHeaderItem phi = null;

                    QbKey lastQbKey = QbKey.Create("last");
                    QbKey dotLastQbKey = QbKey.Create(".last");

                    do
                    {
                        phi = new PakHeaderItem();

                        phi.HeaderStart = (uint)st.Position;
                        phi.IsStoredInPak = true;

                        phi.FileType = QbKey.Create(br.ReadUInt32(_pakFormat.EndianType));

                        //if the entry has the file type of last then we're done
                        if (phi.FileType == lastQbKey || phi.FileType == dotLastQbKey)
                            break;

                        phi.FileOffset = br.ReadUInt32(_pakFormat.EndianType);
                        phi.FileLength = br.ReadUInt32(_pakFormat.EndianType);
                        phi.PakFullFileNameQbKey = br.ReadUInt32(_pakFormat.EndianType);
                        phi.FullFilenameQbKey = br.ReadUInt32(_pakFormat.EndianType);
                        phi.NameOnlyCrc = br.ReadUInt32(_pakFormat.EndianType);
                        phi.Unknown = br.ReadUInt32(_pakFormat.EndianType);
                        phi.Flags = (PakHeaderFlags)br.ReadUInt32(_pakFormat.EndianType);

                        if ((phi.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename)
                        {
                            uint crc = 0;

                            //get any Crc
                            if (phi.FullFilenameQbKey != 0)
                                crc = phi.FullFilenameQbKey;
                            else if (phi.PakFullFileNameQbKey != 0)
                                crc = phi.PakFullFileNameQbKey;
                            else if (phi.NameOnlyCrc != 0)
                                crc = phi.NameOnlyCrc;

                            if (!debugFile)
                            {
                                uint crc2 = 0;
                                //get a crc that exists in the debug names
                                if (qbKeyFilenames.ContainsKey(phi.FullFilenameQbKey))
                                    crc2 = phi.FullFilenameQbKey;
                                else if (qbKeyFilenames.ContainsKey(phi.PakFullFileNameQbKey))
                                    crc2 = phi.PakFullFileNameQbKey;
                                else if (qbKeyFilenames.ContainsKey(phi.NameOnlyCrc))
                                    crc2 = phi.NameOnlyCrc;

                                //if 0 then get any crc
                                if (crc2 != 0)
                                {
                                    phi.Filename = qbKeyFilenames[crc2].Filename;
                                    phi.DebugQbKey = qbKeyFilenames[crc2].DebugQbKey;
                                    crc = crc2;
                                }
                            }

                            if (phi.Filename == null)
                            {
                                if (crc != 0)
                                    phi.Filename = crc.ToString("X").PadLeft(8, '0');
                                else
                                    phi.Filename = string.Format("Unknown={0}", phi.HeaderStart.ToString("X").PadLeft(8, '0'));
                            }
                        }
                        else
                            phi.Filename = UTF8Encoding.UTF8.GetString(br.ReadBytes(PakHeaderItem.FileNameMaxLength)).TrimEnd(new char[] { '\0' });

                        try
                        {
                            _pakHeaders.Add(phi.Filename.ToLower(), phi);
                        }
                        catch (Exception ex)
                        {
                            throw new ApplicationException(string.Format("Error adding '{0}' to headers: {1}", phi.Filename, ex.Message));
                        }

                        if (phi.HeaderStart + phi.FileOffset < minOffset)
                            minOffset = phi.HeaderStart + phi.FileOffset;

                        if (phi.HeaderStart + phi.FileOffset > maxOffset)
                            maxOffset = phi.HeaderStart + phi.FileOffset;

                    }
                    while (1 == 1); //minOffset > fs.Position + 0x100); //drop out if we reach the data

                    //this is a simple hack/fix to cater for padding on PAK files,
                    //it relies on the data starting at the top of the PAB file (which it always does, currently)
                    _requiresPab = maxOffset >= st.Length;

                    if (!debugFile) //only when loading pak
                        _pakFormat.PakPabMinDataOffset = minOffset; //remember this value

                    //detect GH5 PAB files
                    if (_requiresPab)
                    {
                        foreach (PakHeaderItem ph in _pakHeaders.Values)
                            ph.FileOffset += (uint)(_pakFileLength - _pakFormat.PakPabMinDataOffset) - (_pakFormat.PakPabMinDataOffset == 0 ? ph.HeaderStart : 0); //gh5 doesn't hold the offset in relation to the data.
                        minOffset = _pakFileLength;
                    }

                }
            }

            _qbFilenames = new string[_pakHeaders.Count];
            int i = 0;
            foreach (PakHeaderItem hi in _pakHeaders.Values)
                _qbFilenames[i++] = hi.Filename;

            StructItemChildrenType s;
            if (!debugFile)
                s = this.StructItemChildrenType;  //auto detect the structitemchildren type
        }
Example #18
0
 public QbFile(string filename, PakFormat pakFormat) : this(filename, "", pakFormat)
 {
 }
Example #19
0
 public PakEditor(PakFormat pakFormat) : this(pakFormat, false)
 {
 }
Example #20
0
        private void parsePak(PakFormat pakFormat, bool debugFile)
        {
            _debugFile   = debugFile;
            _pakFormat   = pakFormat;
            _pakFilename = (!_debugFile ? _pakFormat.FullPakFilename : _pakFormat.FullDebugFilename);

            Dictionary <uint, PakDbgQbKey> qbKeyFilenames = new Dictionary <uint, PakDbgQbKey>();

            //if PC or xbox then we need to look up the filename from the debug file
            //create a PakEditor and load the debug pak, then load all internal debug files, add the first line to our filenames dictionary
            if (!debugFile) // && (_pakFormat.PakFormatType == PakFormatType.PC || _pakFormat.PakFormatType == PakFormatType.XBox))
            {
                try
                {
                    _pakFormat.Decompress();
                    _pakFilename = _pakFormat.FullPakFilename;
                }
                catch (Exception ex)
                {
                    throw new Exception("Decompression Error", ex);
                }


                if (_pakFormat.DebugFileExists && _debugFile) // cancer
                {
                    string    debugFileContents;
                    string    filename;
                    uint      crc;
                    PakEditor pakDebug = new PakEditor(new PakFormat(_pakFormat.FullDebugFilename, "", _pakFormat.FullDebugFilename, _pakFormat.PakFormatType), true);
                    foreach (PakHeaderItem dphi in pakDebug.Headers.Values)
                    {
                        debugFileContents = string.Empty;
                        filename          = string.Empty;
                        crc = 0;
                        if (dphi.FullFilenameQbKey != 0)
                        {
                            crc = dphi.FullFilenameQbKey;
                        }
                        else if (dphi.PakFullFileNameQbKey != 0)
                        {
                            crc = dphi.PakFullFileNameQbKey;
                        }
                        else if (dphi.NameOnlyCrc != 0)
                        {
                            crc = dphi.NameOnlyCrc;
                        }

                        if (crc != 0)
                        {
                            filename = crc.ToString("X").PadLeft(8, '0');
                            if (pakDebug.Headers.ContainsKey(filename.ToLower()))
                            {
                                debugFileContents = pakDebug.ExtractFileToString(filename);

                                if (debugFileContents.Length != 0)
                                {
                                    addDebugFilename(debugFileContents, qbKeyFilenames, crc);
                                }
                            }
                        }
                    }
                }
            }

            long minOffset = uint.MaxValue;
            long maxOffset = 0;

            _pakHeaders = new Dictionary <string, PakHeaderItem>();

            using (Stream st = File.Open(_pakFilename, FileMode.Open, FileAccess.Read))
            {
                _pakFileLength = st.Length;

                using (BinaryEndianReader br = new BinaryEndianReader(st))
                {
                    PakHeaderItem phi = null;

                    QbKey lastQbKey    = QbKey.Create("last");
                    QbKey dotLastQbKey = QbKey.Create(".last");

                    do
                    {
                        phi = new PakHeaderItem();

                        phi.HeaderStart   = (uint)st.Position;
                        phi.IsStoredInPak = true;

                        phi.FileType = QbKey.Create(br.ReadUInt32(_pakFormat.EndianType));

                        //if the entry has the file type of last then we're done
                        if (phi.FileType == lastQbKey || phi.FileType == dotLastQbKey)
                        {
                            break;
                        }

                        phi.FileOffset           = br.ReadUInt32(_pakFormat.EndianType);
                        phi.FileLength           = br.ReadUInt32(_pakFormat.EndianType);
                        phi.PakFullFileNameQbKey = br.ReadUInt32(_pakFormat.EndianType);
                        phi.FullFilenameQbKey    = br.ReadUInt32(_pakFormat.EndianType);
                        phi.NameOnlyCrc          = br.ReadUInt32(_pakFormat.EndianType);
                        phi.Unknown = br.ReadUInt32(_pakFormat.EndianType);
                        phi.Flags   = (PakHeaderFlags)br.ReadUInt32(_pakFormat.EndianType);

                        if ((phi.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename)
                        {
                            uint crc = 0;

                            //get any Crc
                            if (phi.FullFilenameQbKey != 0)
                            {
                                crc = phi.FullFilenameQbKey;
                            }
                            else if (phi.PakFullFileNameQbKey != 0)
                            {
                                crc = phi.PakFullFileNameQbKey;
                            }
                            else if (phi.NameOnlyCrc != 0)
                            {
                                crc = phi.NameOnlyCrc;
                            }

                            if (!debugFile)
                            {
                                uint crc2 = 0;
                                //get a crc that exists in the debug names
                                if (qbKeyFilenames.ContainsKey(phi.FullFilenameQbKey))
                                {
                                    crc2 = phi.FullFilenameQbKey;
                                }
                                else if (qbKeyFilenames.ContainsKey(phi.PakFullFileNameQbKey))
                                {
                                    crc2 = phi.PakFullFileNameQbKey;
                                }
                                else if (qbKeyFilenames.ContainsKey(phi.NameOnlyCrc))
                                {
                                    crc2 = phi.NameOnlyCrc;
                                }

                                //if 0 then get any crc
                                if (crc2 != 0)
                                {
                                    phi.Filename   = qbKeyFilenames[crc2].Filename;
                                    phi.DebugQbKey = qbKeyFilenames[crc2].DebugQbKey;
                                    crc            = crc2;
                                }
                            }

                            if (phi.Filename == null)
                            {
                                if (crc != 0)
                                {
                                    phi.Filename = crc.ToString("X").PadLeft(8, '0');
                                }
                                else
                                {
                                    phi.Filename = string.Format("Unknown={0}", phi.HeaderStart.ToString("X").PadLeft(8, '0'));
                                }
                            }
                        }
                        else
                        {
                            phi.Filename = UTF8Encoding.UTF8.GetString(br.ReadBytes(PakHeaderItem.FileNameMaxLength)).TrimEnd(new char[] { '\0' });
                        }

                        try
                        {
                            _pakHeaders.Add(phi.Filename.ToLower(), phi);
                        }
                        catch (Exception ex)
                        {
                            throw new ApplicationException(string.Format("Error adding '{0}' to headers: {1}", phi.Filename, ex.Message));
                        }

                        if (phi.HeaderStart + phi.FileOffset < minOffset)
                        {
                            minOffset = phi.HeaderStart + phi.FileOffset;
                        }

                        if (phi.HeaderStart + phi.FileOffset > maxOffset)
                        {
                            maxOffset = phi.HeaderStart + phi.FileOffset;
                        }
                    }while (1 == 1); //minOffset > fs.Position + 0x100); //drop out if we reach the data



                    //this is a simple hack/fix to cater for padding on PAK files,
                    //it relies on the data starting at the top of the PAB file (which it always does, currently)
                    _requiresPab = maxOffset >= st.Length;

                    if (!debugFile)                                 //only when loading pak
                    {
                        _pakFormat.PakPabMinDataOffset = minOffset; //remember this value
                    }
                    //detect GH5 PAB files
                    if (_requiresPab)
                    {
                        foreach (PakHeaderItem ph in _pakHeaders.Values)
                        {
                            ph.FileOffset += (uint)(_pakFileLength - _pakFormat.PakPabMinDataOffset) - (_pakFormat.PakPabMinDataOffset == 0 ? ph.HeaderStart : 0); //gh5 doesn't hold the offset in relation to the data.
                        }
                        minOffset = _pakFileLength;
                    }
                }
            }

            _qbFilenames = new string[_pakHeaders.Count];
            int i = 0;

            foreach (PakHeaderItem hi in _pakHeaders.Values)
            {
                _qbFilenames[i++] = hi.Filename;
            }

            StructItemChildrenType s;

            if (!debugFile)
            {
                s = this.StructItemChildrenType;  //auto detect the structitemchildren type
            }
        }
Example #21
0
        private void btnPabFile_Click(object sender, EventArgs e)
        {
            string filePak = getBestFullFilename(txtPakFile.Text);
            string filePab = getBestFullFilename(txtPabFile.Text);
            string fileDbg = getBestFullFilename(txtDebugFile.Text);

            PakFormat pts = new PakFormat(filePak, filePab, fileDbg, formatToPakFormatType(cboFormatType.Text));
            openInput.Filter = string.Format("{0} (*.pab.{1})|*.pab.{1}|All files (*.*)|*.*", pts.PakFormatType.ToString(), pts.FileExtension);
            openInput.Title = string.Format("Open {0} PAB file", pts.PakFormatType.ToString());

            openInput.FileName = filePab;
            if (openInput.ShowDialog(this) != DialogResult.Cancel)
            {
                txtPabFile.Text = openInput.FileName;
            }
        }
Example #22
0
 /// Open using a stream.
 public QbFile(Stream stream, string debugFileContents, PakFormat pakFormat) : this("", debugFileContents, stream, pakFormat)
 {
 }
Example #23
0
        private void addBonusSongNotes(DirectoryInfo rootPath, QbKey source, QbKey dest, PakEditor qbPak)
        {
            string srcFolder = string.Format(@"{0}\songs", rootPath.FullName.TrimEnd('\\'));
            string srcMask = string.Format(@"{0}*.pak.ngc", source.Text);

            string[] srcFi = Directory.GetFiles(srcFolder, srcMask, SearchOption.TopDirectoryOnly);

            if (_project.GameInfo.Game == Game.GHA_Wii)
            {
                //GHA holds the section text in the main qb.pak file
                string destNotes = string.Format(@"songs\{0}.mid_text.qb.ngc", dest.Text);
                if (!qbPak.Headers.ContainsKey(destNotes.ToLower()))
                {
                    QbFile qbNotes = qbPak.ReadQbFile(string.Format(@"songs\{0}.mid_text.qb.ngc", source.Text));
                    //copy notes section qb file to new file in qb.pak.ngc
                    qbPak.AddFile(qbNotes, destNotes, QbKey.Create(".qb"), true);
                }
            }

            foreach (string src in srcFi)
            {
                FileInfo srcF = new FileInfo(src);
                string dst = string.Format(@"{0}\{1}{2}", srcF.Directory.FullName.TrimEnd('\\'), dest.Text, srcF.Name.Substring(source.Text.Length));

                //skip if exists
                if (File.Exists(dst) || !Regex.IsMatch(src, string.Format(@"{0}(|_.)\.pak\.ngc$", source.Text))) //only allow "" or _<fgis>
                    continue;

                File.Copy(src, dst, true);

                PakFormat pf = new PakFormat(dst, string.Empty, string.Empty, PakFormatType.Wii, false);
                PakEditor pe = new PakEditor(pf, false);
                string qbDst;
                QbFile qb;
                Dictionary<uint, string> srcQk;
                string dstS;
                foreach (string qbSrc in pe.QbFilenames)
                {
                    qbDst = qbSrc.ToLower().Replace(source.Text.ToLower(), dest.Text.ToLower());
                    pe.RenameFile(qbSrc, qbDst, QbKey.Create(".mqb"));

                    if (!qbSrc.Contains(".mid_text."))
                    {
                        //map the section QbKeys
                        qb = pe.ReadQbFile(qbDst);

                        srcQk = getMidItems(source.Text);
                        foreach (QbItemBase qib in qb.Items)
                        {
                            if (qib.ItemQbKey != null)
                            {
                                if (srcQk.ContainsKey(qib.ItemQbKey.Crc))
                                {
                                    dstS = string.Format("{0}{1}", dest.Text, srcQk[qib.ItemQbKey.Crc].Substring(source.Text.Length));
                                    qib.ItemQbKey = QbKey.Create(dstS);
                                }
                                //else
                                //    throw new ApplicationException("Item QBKey not recognised");
                            }
                        }
                        pe.ReplaceFile(qbDst, qb);
                    }

                }
            }
        }
Example #24
0
 /// Open using a stream.
 public QbFile(Stream stream, PakFormat pakFormat) : this("", "", stream, pakFormat)
 {
 }
Example #25
0
 public QbFile(string filename, PakFormat pakFormat)
     : this(filename, "", pakFormat)
 {
 }
Example #26
0
        private int replaceNotesItems()
        {
            int notesLength = 0; //position of final notes item (last fret)
            QbKey song = this.SongQb.Id;
            string songName = song.Text;

            GameFile gf = _project.FileManager.File(_project.GameInfo.GetNotesFilename(song));

            if (gf == null)
                return notesLength; //return 0, this prevents exceptions in the ISO tool which doesn't replace notes

            string notesPak = gf.LocalName;

            PakFormat pf = new PakFormat(notesPak, "", "", _project.GameInfo.PakFormatType);
            PakEditor pak = new PakEditor(pf);
            QbFile qb = pak.ReadQbFile(_project.GameInfo.GetNotesQbFilename(song));

            //modify the mid file
            //clearAllQbItems(qb, this.Notes.GhItems,
            //    QbKey.Create(string.Format("{0}_TimeSig", songName)),
            //    QbKey.Create(string.Format("{0}_FretBars", songName)),
            //    QbKey.Create(string.Format("{0}_Markers", songName)));

            QbFile qbText;
            if (!_project.GameInfo.MidTextInQbPak)
                qbText = pak.ReadQbFile(_project.GameInfo.GetNotesTextQbFilename(song));
            else
            {
                qbText = _project.FileManager.QbPakEditor.ReadQbFile(_project.GameInfo.GetNotesTextQbFilename(song));
            }

            QbItemArray ar;

            int[] ints;
            int offset;

            //calculate ms to add to wav to ensure notes don't start before the given time (in seconds)
            if (this.Notes.MinNoteOffsetSynced < this.MinMsBeforeNotesStart)
                _startPaddingMs = this.MinMsBeforeNotesStart - this.Notes.MinNoteOffsetSynced;

            this.Length = this.Audio.AudioLength + _startPaddingMs;

            offset = this.Notes.BaseFile.NonNoteSyncOffset + _startPaddingMs;

            int[] frets = (int[])this.Notes.BaseFile.Frets.Clone(); //clone in case class is holding reference
            for (int i = 0; i < frets.Length; i++)
                frets[i] += offset;

            //this function sets _fretPadding, another padding value.  It adds padding to allow a properly spaced fret to be at position 0
            frets = adjustFrets(frets);
            notesLength = frets[frets.Length - 1];

            //set the track length to the notes length if it's longer
            if (this.Length < notesLength)
                this.Length = notesLength;
            else
                this.Length += _fretPadding;

            offset += _fretPadding;

            int[] timeSig = (int[])this.Notes.BaseFile.Parser.GetTimeSig().Clone(); //clone in case class is holding reference

            if (timeSig.Length == 0)
                timeSig = new int[] { 0, 4, 4 };

            for (int i = 0; i < timeSig.Length; i += 3)
                timeSig[i] = (int)findNearestFret((uint)(timeSig[i] + offset), frets);

            timeSig[0] = 0; //if the first item is not 0 the song won't load??.

            NotesMarker[] markers = (NotesMarker[])this.Notes.BaseFile.Parser.GetNotesMarkers().Clone(); //clone in case class is holding reference
            for (int i = 0; i < markers.Length; i += 3)
                markers[i] = new NotesMarker(markers[i].Title, markers[i].Offset + offset); //perform deep clone

            int oldSustainTrigger;
            int sustainTrigger;
            int nextNote;
            int[] faceOffP1Ints = new int[0];
            int[] faceOffP2Ints = new int[0];
            GhNotesItem faceOffItem = null;

            //we have a face off item for each mapping, GH3 only has one per song,  find the one with the hardest difficulty (They're always the same anyway)
            foreach (GhNotesItem ghi in this.Notes.GhItems)
            {
                if (ghi.IsMapped && ghi.MappedFileItem.FaceOffP1Count != 0 && ghi.MappedFileItem.FaceOffP2Count != 0)
                {
                    //non generated overrides generated
                    if (faceOffItem == null || faceOffItem.MappedFileItem.HasGeneratedFaceOff || (ghi.MappedFileItem.HasGeneratedFaceOff == faceOffItem.MappedFileItem.HasGeneratedFaceOff))
                    {
                        if (faceOffItem == null || ((int)faceOffItem.Difficulty < (int)ghi.Difficulty && ghi.Type == NotesType.Guitar)) //guitar is more reliable
                            faceOffItem = ghi;
                    }
                }
            }

            if (faceOffItem != null)
            {
                offset = faceOffItem.MappedFileItem.SyncOffset + _startPaddingMs + _fretPadding;

                faceOffP1Ints = (int[])faceOffItem.MappedFileItem.FaceOffP1.Clone();
                for (int i = 0; i < faceOffP1Ints.Length; i += 2)
                    faceOffP1Ints[i] += offset;

                faceOffP2Ints = (int[])faceOffItem.MappedFileItem.FaceOffP2.Clone();
                for (int i = 0; i < faceOffP2Ints.Length; i += 2)
                    faceOffP2Ints[i] += offset;
            }

            foreach (GhNotesItem ghi in this.Notes.GhItems)
            {
                if (ghi.IsMapped)
                {
                    oldSustainTrigger = ghi.MappedFileItem.SustainTrigger;
                    sustainTrigger = (int)((float)(frets[1] - frets[0]) / 2F);
                    ghi.MappedFileItem.SustainTrigger = sustainTrigger;

                    //Offset notes
                    offset = ghi.MappedFileItem.SyncOffset + _startPaddingMs + _fretPadding;

                    ints = (int[])ghi.MappedFileItem.Notes.Clone(); //don't modify original notes
                    int startFret = 0;
                    for (int i = 0; i < ints.Length; i += 3)
                    {
                        ints[i] += offset;
                        if (i + 3 < ints.Length)
                            nextNote = ints[i + 3] + offset;
                        else
                            nextNote = 0;

                        //loop to find fret length note is in to calculate if note is sustained
                        int fpos;
                        int fretLen = 0;
                        bool isSustained = false;
                        for (int c = startFret; c < frets.Length; c++)
                        {
                            if ((fpos = frets[c]) > ints[i] && c > 0) //careful fpos is assigned here
                            {
                                startFret = c; //next time start from here
                                fretLen = fpos - frets[c - 1];
                                isSustained = ints[i + 1] > ((fretLen / 192.0) * (double)(192 >> 2));  //(fretLen / 192.0 == bpmUnit
                                break;
                            }
                        }
                        //clip sustained notes to GH3 mode
                        if (isSustained)
                            ints[i + 1] = setSustain(ints[i], ints[i + 1], nextNote, oldSustainTrigger / 2, sustainTrigger / 2, this.Notes.Gh3SustainClipping);
                    }
                    int[] notes = ints;

                    //if this is a boss battle then remove notes that are not within the face off sections
                    if (this.IsBoss && faceOffItem != null)
                        ints = convertBossNotesToFaceOff(ints, ghi.Type == NotesType.Guitar ? faceOffP1Ints : faceOffP2Ints);
                    ints = adjustNotes(ints); //merge any notes that are really close together

                    //replace track notes
                    ar = (QbItemArray)qb.FindItem(ghi.SongNotesQbKey, false);
                    replaceQbItems(ar, ints, false);
                    setLength(ar, this.Length, 3, frets, false);

                    //Offset star power
                    ints = (int[])ghi.MappedFileItem.StarPower.Clone(); //don't modify original starpower
                    for (int i = 0; i < ints.Length; i += 3)
                        ints[i] += offset;
                    //if (faceOffItem != null)
                    //    alignBattleStarPowerToFaceOff(ints, ghi.Type == NotesType.Guitar ? faceOffP1Ints : faceOffP2Ints);
                    ints = adjustBattleStarPower(ints, notes);

                    //replace star power
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerQbKey, false);
                    replaceQbItems(ar, this.Notes.ForceNoStarPower ? new int[0] : ints, true); //optionally set to no star power
                    setLength(ar, this.Length, 3, frets, false);

                    int[] sp = ints;

                    //Offset star battle mode
                    ints = (int[])ghi.MappedFileItem.BattlePower.Clone();
                    for (int i = 0; i < ints.Length; i += 3)
                        ints[i] += offset;
                    //if (faceOffItem != null)
                    //    alignBattleStarPowerToFaceOff(ints, ghi.Type == NotesType.Guitar ? faceOffP1Ints : faceOffP2Ints);
                    ints = adjustBattleStarPower(ints, notes);

                    if (ints.Length == 0) //if no ints then use star power
                        ints = (int[])sp.Clone(); //just to ensure there's no issue with 2 references pointing at the same array

                    //replace star battle notes
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerBattleQbKey, false);
                    replaceQbItems(ar, ints, true);
                    setLength(ar, this.Length, 3, frets, false);

                }
                else
                {
                    ar = (QbItemArray)qb.FindItem(ghi.SongNotesQbKey, false);
                    clearQbItems(ar);
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerQbKey, false);
                    clearQbItems(ar);
                    ar = (QbItemArray)qb.FindItem(ghi.SongStarPowerBattleQbKey, false);
                    clearQbItems(ar);
                }
            }

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Easy.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Medium.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Hard.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_GuitarCoop_{1}", songName, NotesDifficulty.Expert.ToString())), false);
            clearQbItems(ar);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Easy.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Medium.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Hard.ToString())), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Song_RhythmCoop_{1}", songName, NotesDifficulty.Expert.ToString())), false);
            clearQbItems(ar);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP1", songName)), false);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP2", songName)), false);
            clearQbItems(ar);

            //start with expert guitar and work down the difficulties to find a GHItem with Face off, copy in to BOss Battle also

            if (faceOffItem != null)
            {
                QbItemArray fo1 = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_FaceOffP1", songName)), false);
                QbItemArray fo2 = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_FaceOffP2", songName)), false);
                if (faceOffItem.IsMapped && faceOffItem.MappedFileItem != null && faceOffItem.MappedFileItem.FaceOffP1Count + faceOffItem.MappedFileItem.FaceOffP2Count != 0)
                {
                    faceOffP1Ints = adjustFaceOff(faceOffP1Ints);
                    replaceQbItems(fo1, faceOffP1Ints, true, 2);

                    //ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP1", songName)), false);
                    //replaceQbItems(ar, faceOffP1Ints, true, 2);

                    faceOffP2Ints = adjustFaceOff(faceOffP2Ints);
                    replaceQbItems(fo2, faceOffP2Ints, true, 2);

                    //ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_BossBattleP2", songName)), false);
                    //replaceQbItems(ar, faceOffP2Ints, true, 2);
                }
                else
                {
                    clearQbItems(fo1);
                    clearQbItems(fo2);
                }

            }

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_TimeSig", songName)), false);
            replaceQbItems(ar, timeSig, true);
            setLength(ar, this.Length, 3, frets, false);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_FretBars", songName)), false);
            replaceQbItems(ar, frets, false);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Markers", songName)), false);
            if (markers.Length != 0)
                setMarkers(frets, ar, qbText, markers);
            else
                calculateMarkers(frets, ar, qbText);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Scripts_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Anim_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Triggers_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Cameras_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Lightshow_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Crowd_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Drums_Notes", songName)), false);
            ////setLength(ar, this.Length, 3, frets, true);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Performance_Notes", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);

            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Scripts", songName)), false);
            if (this.SongQb.IsBoss) //set the death drain marker to the correct location
                setDeathDrain(ar, markers);
            else
                setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Anim", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Triggers", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Cameras", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Lightshow", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Crowd", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Drums", songName)), false);
            ////setLength(ar, this.Length, 3, frets, true);
            clearQbItems(ar);
            ar = (QbItemArray)qb.FindItem(QbKey.Create(string.Format("{0}_Performance", songName)), false);
            setLength(ar, this.Length, 3, frets, true);
            //clearQbItems(ar);

            qb.AlignPointers();
            qb.IsValid();
            qbText.AlignPointers();
            qbText.IsValid();

            long origPakLen = pak.FileLength;
            string tmpPak = string.Format("{0}_{1}", notesPak, Guid.NewGuid().ToString("N"));
            File.Copy(notesPak, tmpPak);

            if (_project.GameInfo.MidTextInQbPak)
            {
                //save markers to qbPak
                _project.FileManager.QbPakEditor.ReplaceFile(_project.GameInfo.GetNotesTextQbFilename(song), qbText);
            }
            else //save markers to mid pak
            {
                pak.ReplaceFile(_project.GameInfo.GetNotesTextQbFilename(song), qbText);
            }

            //replace notes to mid pak
            pak.ReplaceFile(_project.GameInfo.GetNotesQbFilename(song), qb);

            //pad notes pak with original file
            //add padding to ensure song works - This took over a month of testing to find!!
            //////////using (FileStream fs = new FileStream(notesPak, FileMode.Open, FileAccess.ReadWrite))
            //////////{

            //////////    using (FileStream fsI = new FileStream(tmpPak, FileMode.Open, FileAccess.Read))
            //////////    {
            //////////        fs.Seek(0, SeekOrigin.End);

            //////////        string tag = " -=> NANOOK <=-  PADDING BELOW  ";
            //////////        if (fs.Position + tag.Length < fsI.Length)
            //////////            fs.Write(Encoding.Default.GetBytes(tag), 0, tag.Length);

            //////////        if (fs.Position < fsI.Length)
            //////////        {
            //////////            fsI.Seek(fs.Position, SeekOrigin.Begin);
            //////////            copy(fsI, fs, fsI.Length - fsI.Position);
            //////////        }

            //////////    }
            //////////}

            FileHelper.Delete(tmpPak);

            return notesLength;
        }