Ejemplo n.º 1
0
        public static bool Export(string originalScriptFilename, string databaseFilename, string gracesJapaneseFilename, string newScriptFilename)
        {
            byte[] script = System.IO.File.ReadAllBytes(originalScriptFilename);
            uint   sectionPointerLocation = BitConverter.ToUInt32(script, 0);

            // this is SUPER HACKY but should work
            using (var stream = new System.IO.FileStream(newScriptFilename, System.IO.FileMode.Create)) {
                var entries = GraceNoteDatabaseEntry.GetAllEntriesFromDatabase("Data Source=" + databaseFilename, "Data Source=" + gracesJapaneseFilename);

                // copy whole flie except for the section pointers
                for (int i = 0; i < sectionPointerLocation; ++i)
                {
                    stream.WriteByte(script[i]);
                }

                long pos = stream.Position;
                // remove original strings from the file
                foreach (var entry in entries)
                {
                    stream.Position = entry.PointerRef;
                    RemoveString(stream, stream.ReadUInt32());
                }
                stream.Position = pos;

                // now write the modified strings from the GN db at the end of the file
                foreach (var entry in entries)
                {
                    uint stringLocation = Convert.ToUInt32(stream.Position);
                    stream.Position = entry.PointerRef;
                    stream.WriteUInt32(stringLocation);
                    stream.Position = stringLocation;
                    stream.Write(StringToBytesBlazeUnion(entry.TextEN));
                    stream.WriteByte(0);
                }

                // write the section pointers and replace position
                stream.Position = stream.Position.Align(4);
                uint newSectionPointerLocation = Convert.ToUInt32(stream.Position);
                for (uint i = sectionPointerLocation; i < script.Length; ++i)
                {
                    stream.WriteByte(script[i]);
                }
                stream.Position = 0;
                stream.WriteUInt32(newSectionPointerLocation);
            }

            return(true);
        }
Ejemplo n.º 2
0
        public static bool Export( string originalScriptFilename, string databaseFilename, string gracesJapaneseFilename, string newScriptFilename )
        {
            byte[] script = System.IO.File.ReadAllBytes( originalScriptFilename );
            uint sectionPointerLocation = BitConverter.ToUInt32( script, 0 );

            // this is SUPER HACKY but should work
            using ( var stream = new System.IO.FileStream( newScriptFilename, System.IO.FileMode.Create ) ) {
                var entries = GraceNoteDatabaseEntry.GetAllEntriesFromDatabase( "Data Source=" + databaseFilename, "Data Source=" + gracesJapaneseFilename );

                // copy whole flie except for the section pointers
                for ( int i = 0; i < sectionPointerLocation; ++i ) {
                    stream.WriteByte( script[i] );
                }

                long pos = stream.Position;
                // remove original strings from the file
                foreach ( var entry in entries ) {
                    stream.Position = entry.PointerRef;
                    RemoveString( stream, stream.ReadUInt32() );
                }
                stream.Position = pos;

                // now write the modified strings from the GN db at the end of the file
                foreach ( var entry in entries ) {
                    uint stringLocation = Convert.ToUInt32( stream.Position );
                    stream.Position = entry.PointerRef;
                    stream.WriteUInt32( stringLocation );
                    stream.Position = stringLocation;
                    stream.Write( StringToBytesBlazeUnion( entry.TextEN ) );
                    stream.WriteByte( 0 );
                }

                // write the section pointers and replace position
                stream.Position = stream.Position.Align( 4 );
                uint newSectionPointerLocation = Convert.ToUInt32( stream.Position );
                for ( uint i = sectionPointerLocation; i < script.Length; ++i ) {
                    stream.WriteByte( script[i] );
                }
                stream.Position = 0;
                stream.WriteUInt32( newSectionPointerLocation );
            }

            return true;
        }
Ejemplo n.º 3
0
        public static int Execute( List<string> args )
        {
            if ( args.Count == 0 ) {
                Console.WriteLine( "This is intended to help extracting skit audio from the Xbox 360 game files." );
                Console.WriteLine( "Do the following in order:" );
                Console.WriteLine( "-- unpack chat.svo (FPS4 archive, with HyoutaTools -> ToVfps4e)" );
                Console.WriteLine( "-- decompress individual skit with xbdecompress" );
                Console.WriteLine( "-- unpack skit (FPS4 archive, with HyoutaTools -> ToVfps4e)" );
                Console.WriteLine( "-- cut SE3 header from audio file to get a nub archive" );
                Console.WriteLine( "   (file 0004, seems to be 0x800 bytes for skits but can be bigger, first four bytes of new file should be 0x00020100)" );
                Console.WriteLine( "-- extract nub archive with NUBExt r12beta" );
                Console.WriteLine( "-- this gives you an \"xma\" file that isn't actually an xma, run this tool on it" );
                Console.WriteLine( "-- resulting file is a valid enough xma file that can be converted to WAV with \"toWav\"" );
                return -1;
            }

            string filename = args[0];
            using ( var source = new FileStream( filename, FileMode.Open ) ) {
                using ( var dest = new FileStream( filename + "-real.xma", FileMode.Create ) ) {
                    source.Position = 0x100;
                    int dataLength = (int)( source.Length - source.Position );

                    dest.WriteAscii( "RIFF" );
                    dest.WriteUInt32( (uint)dataLength + 0x34 );
                    dest.WriteAscii( "WAVE" );
                    dest.WriteAscii( "fmt " );

                    dest.WriteUInt32( 0x20 );

                    source.Position = 0xBC;
                    dest.WriteUInt16( source.ReadUInt16().SwapEndian() );
                    dest.WriteUInt16( source.ReadUInt16().SwapEndian() );
                    dest.WriteUInt16( source.ReadUInt16().SwapEndian() );
                    dest.WriteUInt16( source.ReadUInt16().SwapEndian() );
                    dest.WriteUInt16( source.ReadUInt16().SwapEndian() );
                    dest.WriteByte( (byte)source.ReadByte() );
                    dest.WriteByte( (byte)source.ReadByte() );
                    dest.WriteUInt32( source.ReadUInt32().SwapEndian() );
                    dest.WriteUInt32( source.ReadUInt32().SwapEndian() );
                    dest.WriteUInt32( source.ReadUInt32().SwapEndian() );
                    dest.WriteUInt32( source.ReadUInt32().SwapEndian() );
                    dest.WriteByte( (byte)source.ReadByte() );
                    dest.WriteByte( (byte)source.ReadByte() );
                    dest.WriteUInt16( source.ReadUInt16().SwapEndian() );

                    dest.WriteAscii( "data" );
                    dest.WriteUInt32( (uint)dataLength );

                    source.Position = 0x100;
                    Util.CopyStream( source, dest, dataLength );
                }
            }

            return 0;
        }
Ejemplo n.º 4
0
        public void Pack( string[] files, string outFilename, string headerName = null, string metadata = null )
        {
            FileCount = (uint)files.Length + 1;
            HeaderSize = 0x1C;

            EntrySize = 0;
            if ( ContainsStartPointers ) { EntrySize += 4; }
            if ( ContainsSectorSizes ) { EntrySize += 4; }
            if ( ContainsFileSizes ) { EntrySize += 4; }
            if ( ContainsFilenames ) { EntrySize += 0x20; }
            if ( ContainsFiletypes ) { EntrySize += 4; }
            if ( ContainsFileMetadata ) { EntrySize += 4; }

            bool headerToSeparateFile = false;
            if ( headerName != null ) { headerToSeparateFile = true; }

            using ( FileStream f = new FileStream( headerToSeparateFile ? headerName : outFilename, FileMode.Create ) ) {
                // header
                f.Write( Encoding.ASCII.GetBytes( "FPS4" ), 0, 4 );
                f.WriteUInt32( FileCount.ToEndian( Endian ) );
                f.WriteUInt32( HeaderSize.ToEndian( Endian ) );
                f.WriteUInt32( 0 ); // start of first file goes here, will be filled in later
                f.WriteUInt16( EntrySize.ToEndian( Endian ) );
                f.WriteUInt16( ContentBitmask.ToEndian( Endian ) );
                f.WriteUInt32( Unknown2.ToEndian( Endian ) );
                f.WriteUInt32( 0 ); // ArchiveNameLocation, will be filled in later

                // file list
                for ( int i = 0; i < files.Length; ++i ) {
                    var fi = new System.IO.FileInfo( files[i] );
                    if ( ContainsStartPointers ) { f.WriteUInt32( 0 ); } // properly written later
                    if ( ContainsSectorSizes ) { f.WriteUInt32( 0 ); } // properly written later
                    if ( ContainsFileSizes ) { f.WriteUInt32( ( (uint)( fi.Length ) ).ToEndian( Endian ) ); }
                    if ( ContainsFilenames ) {
                        string filename = fi.Name.Truncate( 0x1F );
                        byte[] fnbytes = Util.ShiftJISEncoding.GetBytes( filename );
                        f.Write( fnbytes, 0, fnbytes.Length );
                        for ( int j = fnbytes.Length; j < 0x20; ++j ) {
                            f.WriteByte( 0 );
                        }
                    }
                    if ( ContainsFiletypes ) {
                        string extension = fi.Extension.TrimStart( '.' ).Truncate( 4 );
                        byte[] extbytes = Util.ShiftJISEncoding.GetBytes( extension );
                        f.Write( extbytes, 0, extbytes.Length );
                        for ( int j = extbytes.Length; j < 4; ++j ) {
                            f.WriteByte( 0 );
                        }
                    }
                    if ( ContainsFileMetadata ) {
                        if ( infile != null ) {
                            // copy this from original file, very hacky when filenames/filecount/metadata changes
                            infile.Position = f.Position;
                            f.WriteUInt32( infile.ReadUInt32() );
                        } else {
                            // place a null for now and go back to fix later
                            f.WriteUInt32( 0 );
                        }
                    }
                }

                // at the end of the file list, reserve space for a final entry pointing to the end of the container
                for ( int j = 0; j < EntrySize; ++j ) {
                    f.WriteByte( 0 );
                }

                // the idea is to write a pointer here
                // and at the target of the pointer you have a nullterminated string
                // with all the metadata in a param=data format separated by spaces
                // maybe including a filepath at the start without a param=
                // strings should be after the filelist block but before the actual files
                if ( ContainsFileMetadata && metadata != null ) {
                    for ( int i = 0; i < files.Length; ++i ) {
                        var fi = new System.IO.FileInfo( files[i] );
                        long ptrPos = 0x1C + ( ( i + 1 ) * EntrySize ) - 4;

                        // remember pos
                        uint oldPos = (uint)f.Position;
                        // jump to metaptr
                        f.Position = ptrPos;
                        // write remembered pos
                        f.WriteUInt32( oldPos.ToEndian( Endian ) );
                        // jump to remembered pos
                        f.Position = oldPos;
                        // write meta + nullterm
                        if ( metadata.Contains( 'p' ) ) {
                            string relativePath = GetRelativePath( f.Name, fi.FullName );
                            f.Write( Util.ShiftJISEncoding.GetBytes( relativePath ) );
                        }
                        if ( metadata.Contains( 'n' ) ) {
                            f.Write( Util.ShiftJISEncoding.GetBytes( "name=" + Path.GetFileNameWithoutExtension( fi.FullName ) ) );
                        }
                        f.WriteByte( 0 );
                    }
                }

                // write original archive filepath
                if ( ArchiveName != null ) {
                    // put the location into the header
                    ArchiveNameLocation = Convert.ToUInt32( f.Position );
                    f.Position = 0x18;
                    f.WriteUInt32( ArchiveNameLocation.ToEndian( Endian ) );
                    f.Position = ArchiveNameLocation;

                    // and actually write it
                    byte[] archiveNameBytes = Util.ShiftJISEncoding.GetBytes( ArchiveName );
                    f.Write( archiveNameBytes, 0, archiveNameBytes.Length );
                    f.WriteByte( 0 );
                }

                // fix up file pointers
                {
                    long pos = f.Position;

                    // location of first file
                    if ( headerToSeparateFile ) {
                        FirstFileStart = 0;
                    } else {
                        if ( infile != null ) {
                            // keep FirstFileStart from loaded file, this is a hack
                            // will break if file metadata (names, count, etc.) changes!
                        } else {
                            FirstFileStart = ( (uint)( f.Position ) ).Align( Alignment );
                        }
                    }
                    f.Position = 0xC;
                    f.WriteUInt32( FirstFileStart.ToEndian( Endian ) );

                    // file entries
                    uint ptr = FirstFileStart;
                    for ( int i = 0; i < files.Length; ++i ) {
                        f.Position = 0x1C + ( i * EntrySize );
                        var fi = new System.IO.FileInfo( files[i] );
                        if ( ContainsStartPointers ) { f.WriteUInt32( ptr.ToEndian( Endian ) ); }
                        if ( ContainsSectorSizes ) { f.WriteUInt32( ( (uint)( fi.Length.Align( (int)Alignment ) ) ).ToEndian( Endian ) ); }
                        ptr += (uint)fi.Length.Align( (int)Alignment );
                    }
                    f.Position = 0x1C + ( files.Length * EntrySize );
                    f.WriteUInt32( ptr.ToEndian( Endian ) );

                    f.Position = pos;
                }

                if ( !headerToSeparateFile ) {
                    // pad until files
                    if ( infile != null ) {
                        infile.Position = f.Position;
                        for ( long i = f.Length; i < FirstFileStart; ++i ) {
                            f.WriteByte( (byte)infile.ReadByte() );
                        }
                    } else {
                        for ( long i = f.Length; i < FirstFileStart; ++i ) {
                            f.WriteByte( 0 );
                        }
                    }
                }

                // actually write files
                if ( headerToSeparateFile ) {
                    using ( FileStream dataStream = new FileStream( outFilename, FileMode.Create ) ) {
                        WriteFilesToFileStream( files, dataStream );
                        dataStream.Close();
                    }
                } else {
                    WriteFilesToFileStream( files, f );
                }
            }
        }
Ejemplo n.º 5
0
        public void Write( string outFile, int align = 0x10 )
        {
            var f = new FileStream( outFile, FileMode.Create );

            // create space for header and filelist stuff
            for ( int i = 0; i < FilesOffset; ++i ) { f.WriteByte( 0 ); }

            // create dummy entry
            f.Write( new byte[] { 0x44, 0x55, 0x4D, 0x4D, 0x59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0x10 );

            // write files
            for ( int i = 0; i < Entries.Count; ++i ) {
                if ( Entries[i].Data != null ) {
                    // special case: if multiple files in a row are identical, only add them once and point the offsets at the same data
                    // oddly enough for the two times it happens in the original files, it only does it once, so no idea what is actually
                    // the proper way to handle it, faking it with that last condition
                    if ( i >= 1 && Entries[i - 1].Data != null && Entries[i - 1].Data.Length == Entries[i].Data.Length && Entries[i].Data.Length > 0x30 ) {
                        Entries[i - 1].Data.Position = 0;
                        Entries[i].Data.Position = 0;
                        if ( Entries[i - 1].Data.IsIdentical( Entries[i].Data, Entries[i].Data.Length ) ) {
                            Entries[i].Offset = Entries[i - 1].Offset;
                            continue;
                        }
                    }

                    Entries[i].Offset = (uint)f.Position - FilesOffset;
                    Entries[i].Data.Position = 0;
                    Util.CopyStream( Entries[i].Data, f, (int)Entries[i].Data.Length );
                    while ( f.Length % align != 0 ) { f.WriteByte( 0 ); }
                }
            }

            Filesize = (uint)f.Length;

            // write header
            f.Position = 0;
            f.Write( Encoding.ASCII.GetBytes( Magic ), 0, 8 );
            f.WriteUInt32( Filesize.SwapEndian() );
            f.WriteUInt32( Unknown.SwapEndian() );
            f.WriteUInt32( Filecount.SwapEndian() );
            f.WriteUInt32( FilesOffset.SwapEndian() );
            f.WriteUInt32( Filesize );
            f.WriteUInt32( 0 );

            // write file list
            for ( int i = 0; i < Entries.Count; ++i ) {
                f.Position = 0x20u + i * 0x20u;
                f.WriteUInt32( Entries[i].Offset.SwapEndian() );
                f.WriteUInt32( Entries[i].FilesizeCompressed.SwapEndian() );
                f.WriteUInt32( Entries[i].FilesizeUncompressed.SwapEndian() );
            }

            f.Close();
        }