Beispiel #1
0
        private void ParseNodes(EndianReader reader, EndianReader strings, uint entryoffset, uint dataoffset, NodeEntry root, DirectoryNode dir, List <NodeEntry> nodes)
        {
            reader.Position = entryoffset + root.FirstFileEntry * 20;
            List <FileEntry> files = new List <FileEntry>();

            for (ushort i = 0; i < root.FileCount; i++)
            {
                files.Add(FileEntry.Create(reader));
            }
            foreach (FileEntry entry in files)
            {
                string name = GetString(strings, entry.NameOffset);
                if (entry.ID == 0xFFFF)
                {
                    if (name == "." || name == "..")
                    {
                        continue;
                    }
                    DirectoryNode subdir = new DirectoryNode(name);
                    dir.AddChild(subdir);
                    ParseNodes(reader, strings, entryoffset, dataoffset, nodes[(int)entry.DataOffset], subdir, nodes);
                }
                else
                {
                    dir.AddChild(new FileNode(name, entry.Size, new Substream(reader, dataoffset + entry.DataOffset, entry.Size)));
                }
            }
        }
Beispiel #2
0
        public StfsArchive(Stream stream)
        {
            Stfs = new StfsFile(stream);

            Root = new DirectoryNode();
            Dictionary <int, DirectoryNode> Directories = new Dictionary <int, DirectoryNode>();

            Directories.Add(0xFFFF, Root);

            for (int i = 0; i < Stfs.Files.Count; i++)
            {
                StfsFile.FileDescriptor file   = Stfs.Files[i];
                DirectoryNode           parent = Directories[file.Parent];
                if ((file.Flags & 0x80) != 0)
                {
                    DirectoryNode directory = new DirectoryNode(file.Name);
                    parent.AddChild(directory);
                    Directories.Add(i, directory);
                }
                else
                {
                    parent.AddChild(new FileNode(file.Name, file.Size, new Substream(Stfs.Stream, Stfs.Stream.GetBlockOffset(file.Block), file.Size)));
                }
            }
        }
Beispiel #3
0
        public FPS4(FPS4Base fps4)
        {
            Base = fps4;

            Root = new DirectoryNode();

            for (uint i = 0; i < Base.Files - 1; i++)
            {
                FPS4Base.Node node = Base.Nodes[(int)i];
                Root.AddChild(new FileNode(node.Filename, node.Data));
            }

            Type = Util.ReadCString(Base.Type, 0);             // There's more to the type I'm sure
        }
Beispiel #4
0
        public static void ExportRWK(string path, IEnumerable <FormatData> songs, bool audio)
        {
            Program.Form.Progress.QueueTask(progress => {
                progress.NewTask("Exporting to RawkSD archive", 2);

                List <Stream> streams = new List <Stream>();

                U8 u8 = new U8();
                foreach (FormatData data in songs)
                {
                    DirectoryNode dir = new DirectoryNode(data.Song.ID);
                    u8.Root.AddChild(dir);
                    foreach (string name in data.GetStreamNames())
                    {
                        Stream stream = data.GetStream(name);
                        int id;
                        if (name.Contains('.') && int.TryParse(Path.GetExtension(name).Substring(1), out id))
                        {
                            IFormat format = Platform.GetFormat(id);
                            if (format.Type == FormatType.Audio && (!audio || format == AudioFormatRB2Bink.Instance))
                            {
                                data.CloseStream(stream);
                                continue;
                            }
                        }

                        streams.Add(stream);
                        dir.AddChild(new FileNode(name, stream));
                    }
                }

                progress.Progress();

                Stream ostream = new FileStream(path, FileMode.Create, FileAccess.Write);
                u8.Save(ostream);
                ostream.Close();

                foreach (Stream stream in streams)
                {
                    stream.Close();
                }

                progress.Progress();
                progress.EndTask();
            });
        }
Beispiel #5
0
        public CPK(Stream data)
        {
            EndianReader reader   = new EndianReader(data, Endianness.BigEndian);
            EndianReader lereader = new EndianReader(data, Endianness.LittleEndian);

            if (reader.ReadUInt32() != CpkMagic)
            {
                throw new FormatException();
            }

            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; section size; 0x00;
            }
            Header = new UTF(data);

            if (Header.Rows.Count != 1)
            {
                throw new FormatException();
            }

            UTF.Row mainrow = Header.Rows[0];

            long tocoffset  = (long)(mainrow.FindValue("TocOffset") as UTF.LongValue).Value;
            long etocoffset = (long)(mainrow.FindValue("EtocOffset") as UTF.LongValue).Value;
            long itocoffset = (long)(mainrow.FindValue("ItocOffset") as UTF.LongValue).Value;
            //long dpkitocoffset = (long)(mainrow.FindValue("DpkItoc") as UTF.IntValue).Value;
            long contentoffset = (long)(mainrow.FindValue("ContentOffset") as UTF.LongValue).Value;
            uint filecount     = (mainrow.FindValue("Files") as UTF.IntValue).Value;

            UTF.ShortValue version = mainrow.FindValue("Version") as UTF.ShortValue;
            UTF.IntValue   mode    = mainrow.FindValue("Mode") as UTF.IntValue;
            if (version != null)
            {
                Version = version.Value;
            }
            if (mode != null)
            {
                Mode = mode.Value;
            }

            reader.Position = tocoffset;
            if (reader.ReadUInt32() != TocMagic)
            {
                throw new FormatException();
            }
            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; size; 0x00;
            }
            ToC = new UTF(data);

            reader.Position = etocoffset;
            if (reader.ReadUInt32() != ETocMagic)
            {
                throw new FormatException();
            }
            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; size; 0x00;
            }
            EToC = new UTF(data);

            reader.Position = itocoffset;
            if (reader.ReadUInt32() != ITocMagic)
            {
                throw new FormatException();
            }
            for (int i = 0; i < 3; i++)
            {
                reader.ReadUInt32();                 // Little Endian: 0xFF; size; 0x00;
            }
            IToC = new UTF(data);

            Cache = new DelayedStreamCache();

            Root = new DirectoryNode();
            foreach (var filerow in ToC.Rows)
            {
                UTF.StringValue dirnamevalue = filerow.FindValue("DirName") as UTF.StringValue;
                string          dirname      = string.Empty;
                if (dirnamevalue != null)
                {
                    dirname = dirnamevalue.Value;
                }
                long   offset     = (long)(filerow.FindValue("FileOffset") as UTF.LongValue).Value;
                string filename   = (filerow.FindValue("FileName") as UTF.StringValue).Value;
                uint   packedsize = (filerow.FindValue("FileSize") as UTF.IntValue).Value;
                uint   filesize   = packedsize;

                if (Version == 7)                 // ToGf
                {
                    offset += tocoffset;
                }
                else                 // Need to check ToG:Wii's version/mode
                {
                    offset += contentoffset;
                }

                UTF.IntValue filesizevalue = filerow.FindValue("ExtractSize") as UTF.IntValue;
                if (filesizevalue != null)
                {
                    filesize = filesizevalue.Value;
                }
                else                   // If we must, read the uncompressed size from the internal compressed file itself
                {
                    data.Position = offset;
                    EndianReader littlereader = new EndianReader(data, Endianness.LittleEndian);
                    if (littlereader.ReadUInt64() == 0)
                    {
                        filesize = littlereader.ReadUInt32() + 0x100;
                    }
                }

                DirectoryNode dir       = Root.Navigate(dirname, true) as DirectoryNode;
                Stream        substream = new Substream(data, offset, packedsize);
                try {
                    if (filesize > packedsize)
                    {
                        //throw new Exception();
                        Stream compressed = substream;
                        substream = new DelayedStream(delegate() {
                            Stream ret = new TemporaryStream();
                            CpkCompression.Decompress(compressed, ret);
                            ret.Position = 0;
                            return(ret);
                        });
                        Cache.AddStream(substream);
                    }
                    dir.AddChild(new FileNode(filename, filesize, substream));
                } catch {
                    dir.AddChild(new FileNode(filename, packedsize, substream));
                }
            }

            // TODO: EToc: Groups

            // TODO: IToc: Attributes
        }
Beispiel #6
0
        public Ark(EndianReader hdrstream, params Stream[] arkstreams) : this()
        {
            HdrStream  = hdrstream;
            ArkStreams = arkstreams;

            HdrStream.Position = 0;
            Version            = HdrStream.ReadUInt32();
            uint numArks;
            uint numArks2;

            long[] arkSizes;
            int    stringSize;
            Stream stringTable;
            int    numOffsets;

            int[] offsetTable;
            int   numEntries;

            if (Version == ArkMagic || Version == ArkMagicLE)     // FreQuency
            {
                Version = HdrStream.ReadUInt32();                 // == 2
                int fileoffset = HdrStream.ReadInt32();
                numEntries = HdrStream.ReadInt32();
                int diroffset = HdrStream.ReadInt32();
                numOffsets = HdrStream.ReadInt32();
                int stringoffset = HdrStream.ReadInt32();
                int numStrings   = HdrStream.ReadInt32();
                HdrStream.ReadInt32();
                int sectorSize = HdrStream.ReadInt32();

                HdrStream.Position = diroffset;
                offsetTable        = new int[numOffsets];
                for (int i = 0; i < numOffsets; i++)
                {
                    HdrStream.ReadInt32();                     // Hash + 0x0000
                    offsetTable[i] = HdrStream.ReadInt32();
                }

                HdrStream.Position = stringoffset;
                stringTable        = new MemoryStream();
                EndianReader writer = new EndianReader(stringTable, Endianness.BigEndian);
                for (int i = 0; i < numStrings; i++)
                {
                    writer.Write(Util.ReadCString(HdrStream));
                    writer.Write((byte)0);
                }

                HdrStream.Position = fileoffset;
                for (int i = 0; i < numEntries; i++)
                {
                    HdrStream.ReadInt16();                     // Hash
                    HdrStream.ReadInt16();                     // Flags
                    int  nameoffset   = HdrStream.ReadInt32(); // Filename
                    int  directory    = HdrStream.ReadInt16();
                    int  sectoroffset = HdrStream.ReadInt16();
                    int  sector       = HdrStream.ReadInt32();
                    uint size         = HdrStream.ReadUInt32();
                    HdrStream.ReadInt32();                     // Extracted length

                    stringTable.Position = offsetTable[directory] - stringoffset;
                    string pathname = Util.ReadCString(stringTable);
                    stringTable.Position = nameoffset - stringoffset;
                    string filename = Util.ReadCString(stringTable);

                    DirectoryNode dir = Root.Navigate(pathname, true) as DirectoryNode;
                    dir.AddChild(new FileNode(filename, size, new Substream(HdrStream, sector * sectorSize + sectoroffset, (long)size)));
                }
            }
            else
            {
                if (Version > 5)                   // Invalid version number, encrypted
                {
                    Stream stream = new CryptedDtbStream(HdrStream);
                    HdrStream          = new EndianReader(stream, HdrStream.Endian);
                    HdrStream.Position = 0;
                    Version            = HdrStream.ReadUInt32();
                }

                if (Version <= 2)
                {
                    numArks  = 1;
                    numArks2 = 1;
                    arkSizes = new long[1] {
                        HdrStream.Base.Length
                    };
                    ArkStreams = new Stream[1] {
                        HdrStream.Base
                    };

                    numEntries          = HdrStream.ReadInt32();
                    HdrStream.Position += numEntries * (4 * 4 + 4);
                }
                else if (Version <= 5)
                {
                    numArks  = HdrStream.ReadUInt32();
                    numArks2 = HdrStream.ReadUInt32();

                    arkSizes = new long[numArks];

                    for (int i = 0; i < numArks; i++)
                    {
                        if (Version == 4)
                        {
                            arkSizes[i] = HdrStream.ReadInt64();
                        }
                        else
                        {
                            arkSizes[i] = (long)HdrStream.ReadUInt32();
                        }
                    }

                    if (Version == 5)                       // ark file string list
                    {
                        numArks = HdrStream.ReadUInt32();
                        for (int i = 0; i < numArks; i++)
                        {
                            int strsize = HdrStream.ReadInt32();
                            HdrStream.PadRead(strsize);                             // I'm not using them >.>
                        }
                    }
                }
                else
                {
                    throw new FormatException();
                }

                stringSize  = HdrStream.ReadInt32();
                stringTable = new MemoryStream(HdrStream.ReadBytes(stringSize), false);
                numOffsets  = HdrStream.ReadInt32();
                offsetTable = new int[numOffsets];
                for (int i = 0; i < numOffsets; i++)
                {
                    offsetTable[i] = HdrStream.ReadInt32();
                }

                if (Version <= 2)
                {
                    HdrStream.Position = 0x04;
                }

                numEntries = HdrStream.ReadInt32();

                for (int i = 0; i < numEntries; i++)
                {
                    long offset;
                    if (Version <= 3)
                    {
                        offset = (long)HdrStream.ReadUInt32();
                    }
                    else
                    {
                        offset = HdrStream.ReadInt64();
                    }
                    uint  filenameStringIndex = HdrStream.ReadUInt32();
                    uint  dirnameStringIndex  = HdrStream.ReadUInt32();
                    ulong size = 0;

                    if (Version <= 2)
                    {
                        size = HdrStream.ReadUInt32();
                        HdrStream.ReadInt32();                         // unknown, flags?
                    }
                    else
                    {
                        size = HdrStream.ReadUInt64();
                    }

                    string pathname;
                    if (dirnameStringIndex == 0xFFFFFFFF)
                    {
                        pathname = string.Empty;
                    }
                    else
                    {
                        stringTable.Position = offsetTable[dirnameStringIndex];
                        pathname             = Util.ReadCString(stringTable);
                    }

                    stringTable.Position = offsetTable[filenameStringIndex];
                    string filename = Util.ReadCString(stringTable);

                    DirectoryNode dir = Root.Navigate(pathname, true) as DirectoryNode;
                    int           ark;
                    for (ark = 0; offset >= arkSizes[ark]; offset -= arkSizes[ark++])
                    {
                        ;
                    }
                    if (dir != null)                     // Arks sometimes have paths like "../../etc", so we're just going to ignore them
                    {
                        dir.AddChild(new FileNode(filename, size, new Substream(ArkStreams[ark], offset, (long)size)));
                    }
                }
            }
        }
Beispiel #7
0
        public U8(Stream stream, bool wiidisc) : this()
        {
            EndianReader reader    = new EndianReader(stream, Endianness.BigEndian);
            long         beginning = 0;

            if (!wiidisc)
            {
                beginning = reader.Position;

                int tag = reader.ReadInt32();
                if (tag != Magic)
                {
                    throw new FormatException();
                }
                if (reader.ReadUInt32() != 0x20)
                {
                    throw new FormatException();
                }

                reader.ReadUInt32();                 // header_size

                uint dataOffset = reader.ReadUInt32();
                reader.ReadBytes(0x10);
            }

            // Parse nodes
            uint nodebegin = reader.ReadUInt32();      // Type and name offset

            if ((nodebegin >> 24) != 0x01)             // Root must be a DirectoryNode
            {
                throw new FormatException();
            }
            reader.ReadUInt32();                         // Data Offset
            uint numfiles = reader.ReadUInt32() - 2 + 1; // Size (+1 because we don't want the stack to shit itself)

            DirectoryNode parent   = Root;
            Stack <uint>  dirfiles = new Stack <uint>();

            dirfiles.Push(numfiles);
            for (int i = 0; i < numfiles; i++)
            {
                Node node;
                uint read       = reader.ReadUInt32();
                byte type       = (byte)((read & 0xFF000000) >> 56);
                uint nameOffset = read & 0x00FFFFFF;
                uint fileOffset = reader.ReadUInt32();
                uint filesize   = reader.ReadUInt32();

                if (wiidisc)
                {
                    fileOffset <<= 2;
                }

                switch (type)
                {
                case 0x00:
                    node = new FileNode(null, filesize, new Substream(reader.Base, beginning + fileOffset, filesize));
                    parent.AddChild(node);
                    break;

                case 0x01:
                    node = new DirectoryNode(null);
                    parent.AddChild(node);
                    parent = node as DirectoryNode;
                    dirfiles.Push(filesize - 2);
                    break;

                default:
                    node = new Node();
                    break;
                }

                node.Name = nameOffset.ToString();                 // <-- The most idiotic thing you'll ever see me do.

                while (i == dirfiles.Peek())
                {
                    dirfiles.Pop();
                    parent = parent.Parent;
                }
            }

            NameNodes(stream, Root, reader.Position);
        }
        public override void SaveSong(PlatformData data, FormatData formatdata, ProgressIndicator progress)
        {
            string path = data.Session["maindirpath"] as string;

            string otitle;
            ushort oindex;

            progress.NewTask(10);

            using (DelayedStreamCache cache = new DelayedStreamCache()) {
                progress.SetNextWeight(6);
                string          audioextension = ".mogg";
                Stream          audio          = null;
                Stream          preview        = null;
                AudioFormat     audioformat    = null;
                IList <IFormat> formats        = formatdata.Formats;
                if (formats.Contains(AudioFormatRB2Mogg.Instance))
                {
                    audio       = AudioFormatRB2Mogg.Instance.GetAudioStream(formatdata);
                    preview     = AudioFormatRB2Mogg.Instance.GetPreviewStream(formatdata);
                    audioformat = AudioFormatRB2Mogg.Instance.DecodeAudioFormat(formatdata);
                }
                else if (formats.Contains(AudioFormatRB2Bink.Instance))
                {
                    audio   = AudioFormatRB2Bink.Instance.GetAudioStream(formatdata);
                    preview = AudioFormatRB2Bink.Instance.GetPreviewStream(formatdata, progress);
                    if (!formatdata.HasStream(preview))
                    {
                        cache.AddStream(preview);
                    }
                    audioformat    = AudioFormatRB2Bink.Instance.DecodeAudioFormat(formatdata);
                    audioextension = ".bik";
                }
                else
                {
                    throw new NotSupportedException();
                }

                progress.Progress(6);

                ChartFormat chartformat = (formatdata.GetFormat(FormatType.Chart) as IChartFormat).DecodeChart(formatdata, progress);

                Stream album   = null;
                Stream chart   = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.ChartFile);
                Stream pan     = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.PanFile);
                Stream weights = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.WeightsFile);
                Stream milo    = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.MiloFile);

                progress.SetNextWeight(2);

                if (chart != null && ChartFormatRB.Instance.NeedsFixing(formatdata))
                {
                    formatdata.CloseStream(chart);
                    chart = null;
                }

                if (chart == null)
                {
                    chart = new TemporaryStream();
                    cache.AddStream(chart);
                    AdjustChart(formatdata.Song, audioformat, chartformat).ToMidi().ToMid().Save(chart);
                    chart.Position = 0;
                }

                if (weights == null)
                {
                    weights = new TemporaryStream();
                    cache.AddStream(weights);
                    CreateWeights(weights, chartformat);
                    weights.Position = 0;
                }

                if (pan == null)
                {
                    pan = new TemporaryStream();
                    cache.AddStream(pan);
                    CreatePan(pan, chartformat);
                    pan.Position = 0;
                }

                if (milo == null)
                {
                    milo = formatdata.GetStream(ChartFormatRB.Instance, ChartFormatRB.Milo3File);
                    if (milo == null)
                    {
                        milo = new MemoryStream(Properties.Resources.rawksd_milo);
                    }
                    else
                    {
                        Stream milostream = new TemporaryStream();
                        cache.AddStream(milostream);
                        Milo   milofile = new Milo(new EndianReader(milo, Endianness.LittleEndian));
                        FaceFX fx       = new FaceFX(new EndianReader(milofile.Data[0], Endianness.BigEndian));

                        TemporaryStream fxstream = new TemporaryStream();
                        fx.Save(new EndianReader(fxstream, Endianness.LittleEndian));
                        milofile.Data[0]    = fxstream;
                        milofile.Compressed = true;
                        milofile.Save(new EndianReader(milostream, Endianness.LittleEndian));
                        fxstream.Close();
                        formatdata.CloseStream(milo);
                        milo          = milostream;
                        milo.Position = 0;
                    }
                }

                //if (album == null)
                //	album = new MemoryStream(Properties.Resources.rawksd_albumart);

                progress.Progress(2);

                SongData song = new SongData(formatdata.Song);

                SongsDTA dta = GetSongsDTA(song, audioformat);

                if (album == null)
                {
                    dta.AlbumArt = false;
                }
                else
                {
                    dta.AlbumArt = true;
                }

                dta.Song.MidiFile = "dlc/content/songs/" + song.ID + "/" + song.ID + ".mid";

                DTB.NodeTree dtb = dta.ToDTB(PlatformRawkFile.Instance.IsRawkSD2(song));

                MemoryStream songsdta = new MemoryStream();
                cache.AddStream(songsdta);
                dtb.SaveDTA(songsdta);
                songsdta.Position = 0;

                U8            appdta = new U8();
                DirectoryNode dir    = new DirectoryNode("content");
                appdta.Root.AddChild(dir);
                DirectoryNode songsdir = new DirectoryNode("songs");
                dir.AddChild(songsdir);
                DirectoryNode songdir = new DirectoryNode(song.ID);
                songsdir.AddChild(songdir);
                songdir.AddChild(new FileNode(song.ID + "_prev.mogg", preview));
                songdir.AddChild(new FileNode("songs.dta", songsdta));
                DirectoryNode gendir;
                if (dta.AlbumArt.Value && album != null)
                {
                    gendir = new DirectoryNode("gen");
                    songdir.AddChild(gendir);
                    gendir.AddChild(new FileNode(song.ID + "_nomip_keep.bmp_wii", album));
                }

                U8 appsong = new U8();
                dir = new DirectoryNode("content");
                appsong.Root.AddChild(dir);
                songsdir = new DirectoryNode("songs");
                dir.AddChild(songsdir);
                songdir = new DirectoryNode(song.ID);
                songsdir.AddChild(songdir);
                songdir.AddChild(new FileNode(song.ID + audioextension, audio));
                songdir.AddChild(new FileNode(song.ID + ".mid", chart));
                songdir.AddChild(new FileNode(song.ID + ".pan", pan));
                gendir = new DirectoryNode("gen");
                songdir.AddChild(gendir);
                gendir.AddChild(new FileNode(song.ID + ".milo_wii", milo));
                gendir.AddChild(new FileNode(song.ID + "_weights.bin", weights));

                Stream memoryDta = new TemporaryStream();
                cache.AddStream(memoryDta);
                appdta.Save(memoryDta);

                Stream memorySong = new TemporaryStream();
                cache.AddStream(memorySong);
                appsong.Save(memorySong);

                formatdata.CloseStream(audio);
                formatdata.CloseStream(preview);
                formatdata.CloseStream(chart);
                formatdata.CloseStream(album);
                formatdata.CloseStream(pan);
                formatdata.CloseStream(weights);
                formatdata.CloseStream(milo);

                FindUnusedContent(data, formatdata.Song, out otitle, out oindex);
                TMD tmd = GenerateDummyTMD(otitle);

                dta.Song.Name = "dlc/" + otitle + "/" + Util.Pad(oindex.ToString(), 3) + "/content/songs/" + song.ID + "/" + song.ID;
                dtb           = dta.ToDTB(PlatformRawkFile.Instance.IsRawkSD2(song));
                HarmonixMetadata.SetSongsDTA(song, dtb);

                string dirpath = Path.Combine(Path.Combine(path, "rawk"), "rb2");
                if (!Directory.Exists(Path.Combine(dirpath, "customs")))
                {
                    Directory.CreateDirectory(Path.Combine(dirpath, "customs"));
                }
                Directory.CreateDirectory(Path.Combine(Path.Combine(dirpath, "customs"), song.ID));
                FileStream savestream = new FileStream(Path.Combine(Path.Combine(Path.Combine(dirpath, "customs"), song.ID), "data"), FileMode.Create);
                dtb.Save(new EndianReader(savestream, Endianness.LittleEndian));
                savestream.Close();

                TmdContent contentDta = new TmdContent();
                contentDta.ContentID = oindex;
                contentDta.Index     = oindex;
                contentDta.Type      = 0x4001;

                TmdContent contentSong = new TmdContent();
                contentSong.ContentID = oindex + 1U;
                contentSong.Index     = (ushort)(oindex + 1);
                contentSong.Type      = 0x4001;

                memoryDta.Position = 0;
                contentDta.Hash    = Util.SHA1Hash(memoryDta);
                contentDta.Size    = memoryDta.Length;

                memorySong.Position = 0;
                contentSong.Hash    = Util.SHA1Hash(memorySong);
                contentSong.Size    = memorySong.Length;

                for (int i = 1; i <= oindex + 1; i++)
                {
                    if (i == oindex)
                    {
                        tmd.Contents.Add(contentDta);
                    }
                    else if (i == oindex + 1)
                    {
                        tmd.Contents.Add(contentSong);
                    }
                    else
                    {
                        tmd.Contents.Add(new TmdContent()
                        {
                            Index = (ushort)i, ContentID = (uint)i, Size = 1, Type = 0x4001
                        });
                    }
                }

                tmd.Fakesign();

                uint consoleid = GetConsoleID(path);

                progress.Progress();

                dirpath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(path, "private"), "wii"), "data"), "sZAE");
                TemporaryStream binstream;
                DlcBin          bin;
                if (consoleid != 0 && !File.Exists(Path.Combine(dirpath, "000.bin")))
                {
                    Directory.CreateDirectory(dirpath);
                    binstream = new TemporaryStream();
                    binstream.Write(Properties.Resources.rawksd_000bin, 0, Properties.Resources.rawksd_000bin.Length);
                    binstream.Position = 8;
                    new EndianReader(binstream, Endianness.BigEndian).Write(consoleid);
                    binstream.ClosePersist();
                    File.Move(binstream.Name, Path.Combine(dirpath, "000.bin"));
                    binstream.Close();
                }

                dirpath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(path, "private"), "wii"), "data"), otitle);
                if (!Directory.Exists(dirpath))
                {
                    Directory.CreateDirectory(dirpath);
                }

                binstream        = new TemporaryStream();
                bin              = new DlcBin();
                bin.Bk.ConsoleID = consoleid;
                bin.TMD          = tmd;
                bin.Content      = tmd.Contents[oindex];
                bin.Data         = memoryDta;
                bin.Generate();
                bin.Bk.ContentSize = bin.Bk.TotalSize = 0;
                bin.Bk.TitleID     = 0x00010000535A4145UL;
                bin.Save(binstream);
                binstream.ClosePersist();
                string dtabinpath = Path.Combine(dirpath, Util.Pad(oindex.ToString(), 3) + ".bin");
                Util.Delete(dtabinpath);
                File.Move(binstream.Name, dtabinpath);
                binstream.Close();

                binstream        = new TemporaryStream();
                bin              = new DlcBin();
                bin.Bk.ConsoleID = consoleid;
                bin.TMD          = tmd;
                bin.Content      = tmd.Contents[oindex + 1];
                bin.Data         = memorySong;
                bin.Generate();
                bin.Bk.ContentSize = bin.Bk.TotalSize = 0;
                bin.Bk.TitleID     = 0x00010000535A4145UL;
                bin.Save(binstream);
                binstream.ClosePersist();
                string songbinpath = Path.Combine(dirpath, Util.Pad((oindex + 1).ToString(), 3) + ".bin");
                Util.Delete(songbinpath);
                File.Move(binstream.Name, songbinpath);
                binstream.Close();

                data.Mutex.WaitOne();
                string mainbinpath = Path.Combine(dirpath, "000.bin");
                if (!File.Exists(mainbinpath))
                {
                    binstream        = new TemporaryStream();
                    bin              = new DlcBin();
                    bin.Bk.ConsoleID = consoleid;
                    bin.TMD          = tmd;
                    bin.Content      = tmd.Contents[0];
                    bin.Data         = new MemoryStream(Properties.Resources.rawksd_savebanner, false);
                    bin.Generate();
                    bin.Bk.TitleID = 0x00010000535A4145UL;
                    bin.Save(binstream);
                    binstream.ClosePersist();
                    File.Move(binstream.Name, mainbinpath);
                    binstream.Close();
                }

                AddSongFromBins(data, song, dtabinpath, songbinpath, progress, true);

                SaveDTBCache(data);

                data.Mutex.ReleaseMutex();

                cache.Dispose();

                progress.Progress();
            }

            progress.EndTask();
        }
Beispiel #9
0
        internal static void Export360(string path, FormatData original)
        {
            Program.Form.Progress.QueueTask(progress => {
                progress.NewTask("Exporting to 360 DLC file", 16);

                SongData song = original.Song;

                StfsArchive stfs      = new StfsArchive();
                stfs.Stfs.ContentType = StfsFile.ContentTypes.Marketplace;
                stfs.Stfs.TitleID     = 0x45410829;
                for (int i = 0; i < stfs.Stfs.DisplayName.Length; i++)
                {
                    stfs.Stfs.DisplayName[i] = song.Artist + " - " + song.Name;
                }
                for (int i = 0; i < stfs.Stfs.DisplayDescription.Length; i++)
                {
                    stfs.Stfs.DisplayDescription[i] = "RawkSD DLC - http://rawksd.japaneatahand.com";
                }
                stfs.Stfs.TitleName      = "Rawk Band 2";
                stfs.Stfs.Publisher      = "RawkSD";
                stfs.Stfs.TitleThumbnail = WiiImage.Create(new EndianReader(new MemoryStream(ConsoleHaxx.RawkSD.Properties.Resources.rawksd_albumart), Endianness.LittleEndian)).Bitmap;
                if (song.AlbumArt != null)
                {
                    stfs.Stfs.Thumbnail = song.AlbumArt;
                }
                else
                {
                    stfs.Stfs.Thumbnail = stfs.Stfs.TitleThumbnail;
                }
                StfsFile.SignedHeader header    = new StfsFile.SignedHeader(StfsFile.FileTypes.LIVE);
                stfs.Stfs.Header                = header;
                header.Licenses[0].ID           = 0xFFFFFFFFFFFFFFFF;
                stfs.Stfs.MetadataVersion       = 2;
                StfsFile.PackageDescriptor desc = new StfsFile.PackageDescriptor();
                stfs.Stfs.Descriptor            = desc;
                desc.StructSize          = 0x24;
                desc.BlockSeparation     = 1;
                desc.FileTableBlockCount = 0x100;                 // byte apparently
                stfs.Stfs.TransferFlags  = 0xC0;

                FormatData data = original;

                Program.Form.TaskMutex.WaitOne();
                bool local     = data.PlatformData.Platform == PlatformLocalStorage.Instance;
                bool ownformat = false;
                if (!local && Configuration.MaxConcurrentTasks > 1)
                {
                    data = new TemporaryFormatData(data.Song, data.PlatformData);
                    original.SaveTo(data);
                    ownformat = true;
                }
                Program.Form.TaskMutex.ReleaseMutex();

                Stream songs   = null;
                Stream audio   = null;
                Stream chart   = data.GetStream(ChartFormatRB.Instance, ChartFormatRB.ChartFile);
                Stream pan     = data.GetStream(ChartFormatRB.Instance, ChartFormatRB.PanFile);
                Stream weights = data.GetStream(ChartFormatRB.Instance, ChartFormatRB.WeightsFile);
                Stream milo    = data.GetStream(ChartFormatRB.Instance, ChartFormatRB.MiloFile);
                milo           = new MemoryStream(Properties.Resources.rbn_milo);       // TODO: properly convert milo

                if (milo == null)
                {
                    milo = new MemoryStream(ConsoleHaxx.RawkSD.Properties.Resources.rawksd_milo);
                }

                using (DelayedStreamCache cache = new DelayedStreamCache()) {
                    AudioFormat audioformat = (data.GetFormat(FormatType.Audio) as IAudioFormat).DecodeAudio(data, progress);

                    ushort[] masks = PlatformRB2WiiCustomDLC.RemixAudioTracks(data.Song, audioformat);

                    progress.Progress();

                    // RBN Required DTA settings
                    SongsDTA dta      = PlatformRB2WiiCustomDLC.GetSongsDTA(song, audioformat, false);
                    dta.AlbumArt      = false;
                    dta.Song.Name     = "songs/" + song.ID + "/" + song.ID;
                    dta.Song.MidiFile = "songs/" + song.ID + "/" + song.ID + ".mid";
                    dta.Rating        = 4;
                    dta.SubGenre      = "subgenre_core";
                    dta.Format        = 4;
                    //dta.SongID = 0;
                    dta.Origin = "rb2";
                    //dta.Ugc = 1;
                    //dta.SongLength = 300000;
                    dta.Context    = 2000;
                    dta.BasePoints = 0;
                    if (!dta.TuningOffsetCents.HasValue)
                    {
                        dta.TuningOffsetCents = 0;
                    }

                    audio = new TemporaryStream();
                    cache.AddStream(audio);

                    progress.Progress();

                    progress.SetNextWeight(10);
                    long samples           = audioformat.Decoder.Samples;
                    CryptedMoggStream mogg = new CryptedMoggStream(audio);
                    mogg.WriteHeader();
                    RawkAudio.Encoder encoder = new RawkAudio.Encoder(mogg, audioformat.Mappings.Count, audioformat.Decoder.SampleRate);
                    progress.NewTask("Transcoding Audio", samples);
                    JaggedShortArray buffer = new JaggedShortArray(encoder.Channels, audioformat.Decoder.AudioBuffer.Rank2);
                    AudioFormat.ProcessOffset(audioformat.Decoder, encoder, audioformat.InitialOffset);
                    while (samples > 0)
                    {
                        int read = audioformat.Decoder.Read((int)Math.Min(samples, audioformat.Decoder.AudioBuffer.Rank2));
                        if (read <= 0)
                        {
                            break;
                        }

                        audioformat.Decoder.AudioBuffer.DownmixTo(buffer, masks, read);

                        encoder.Write(buffer, read);
                        samples -= read;
                        progress.Progress(read);
                    }
                    progress.EndTask();
                    progress.Progress(10);

                    encoder.Dispose();
                    audioformat.Decoder.Dispose();
                    audio.Position = 0;

                    dta.Song.TracksCount.Add(audioformat.Mappings.Count(m => m.Instrument == Instrument.Drums));
                    dta.Song.TracksCount.Add(audioformat.Mappings.Count(m => m.Instrument == Instrument.Bass));
                    dta.Song.TracksCount.Add(audioformat.Mappings.Count(m => m.Instrument == Instrument.Guitar));
                    dta.Song.TracksCount.Add(audioformat.Mappings.Count(m => m.Instrument == Instrument.Vocals));
                    dta.Song.TracksCount.Add(audioformat.Mappings.Count(m => m.Instrument == Instrument.Ambient));

                    for (int i = 0; i < dta.Song.Cores.Count; i++)
                    {
                        dta.Song.Cores[i] = -1;
                    }

                    songs = new TemporaryStream();
                    cache.AddStream(songs);
                    dta.ToDTB().SaveDTA(songs);

                    ChartFormat chartformat = (data.GetFormat(FormatType.Chart) as IChartFormat).DecodeChart(data, progress);
                    if (chart != null && ChartFormatRB.Instance.NeedsFixing(data))
                    {
                        data.CloseStream(chart);
                        chart = null;
                    }

                    if (chart == null)
                    {
                        chart = new TemporaryStream();
                        cache.AddStream(chart);
                        PlatformRB2WiiCustomDLC.AdjustChart(song, audioformat, chartformat).ToMidi().ToMid().Save(chart);
                        chart.Position = 0;
                    }

                    if (weights == null)
                    {
                        weights = new TemporaryStream();
                        cache.AddStream(weights);
                        PlatformRB2WiiCustomDLC.CreateWeights(weights, chartformat);
                        weights.Position = 0;
                    }

                    if (pan == null)
                    {
                        pan = new TemporaryStream();
                        cache.AddStream(pan);
                        PlatformRB2WiiCustomDLC.CreatePan(pan, chartformat);
                        pan.Position = 0;
                    }

                    progress.Progress(3);

                    DirectoryNode dir = new DirectoryNode("songs");
                    stfs.Root.AddChild(dir);
                    dir.AddChild(new FileNode("songs.dta", songs));
                    DirectoryNode songdir = new DirectoryNode(song.ID);
                    dir.AddChild(songdir);
                    songdir.AddChild(new FileNode(song.ID + ".mogg", audio));
                    songdir.AddChild(new FileNode(song.ID + ".mid", chart));
                    DirectoryNode gendir = new DirectoryNode("gen");
                    songdir.AddChild(gendir);
                    gendir.AddChild(new FileNode(song.ID + ".milo_xbox", milo));
                    gendir.AddChild(new FileNode(song.ID + "_weights.bin", weights));

                    Stream ostream = new FileStream(path, FileMode.Create);
                    stfs.Save(ostream);
                    ostream.Close();

                    data.CloseStream(audio);
                    data.CloseStream(chart);
                    data.CloseStream(pan);
                    data.CloseStream(weights);
                    data.CloseStream(milo);

                    if (ownformat)
                    {
                        data.Dispose();
                    }

                    progress.Progress();
                    progress.EndTask();
                }
            });
        }