示例#1
0
        public WUDImage(FileInfo file)
        {
            if (file == null || !file.Exists)
            {
                //MessageBox.Show("WUD file is null or does not exist");
                //System.exit(1);
            }

            fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
            BinaryReader br1 = new BinaryReader(fileStream);

            br1.BaseStream.Seek(0, SeekOrigin.Begin);
            byte[] wuxheader = new byte[WUDImageCompressedInfo.WUX_HEADER_SIZE];
            int    n         = br1.Read(wuxheader, 0, WUDImageCompressedInfo.WUX_HEADER_SIZE);
            WUDImageCompressedInfo compressedInfo = new WUDImageCompressedInfo(wuxheader);


            if (compressedInfo.isWUX())
            {
                //MessageBox.Show("Image is compressed");
                this.isCompressed = true;
                this.isSplitted   = false;
                Dictionary <int, long> indexTable = new Dictionary <int, long>();
                long offsetIndexTable             = compressedInfo.offsetIndexTable;
                br1.BaseStream.Seek(offsetIndexTable, SeekOrigin.Begin);

                byte[] tableData = new byte[(int)(compressedInfo.indexTableEntryCount * 0x04)];
                br1.Read(tableData, 0, tableData.Length);
                int cur_offset = 0x00;
                for (long i = 0; i < compressedInfo.indexTableEntryCount; i++)
                {
                    indexTable[(int)i] = BitConverter.ToInt32(tableData, (int)cur_offset);
                    cur_offset        += 0x04;
                }
                compressedInfo.indexTable = indexTable;
                this.compressedInfo       = compressedInfo;
            }
            else
            {
                this.isCompressed = false;
                if (file.Name.Equals(String.Format(WUDDiscReaderSplitted.WUD_SPLITTED_DEFAULT_FILEPATTERN, 1)) && (file.Length == WUDDiscReaderSplitted.WUD_SPLITTED_FILE_SIZE))
                {
                    this.isSplitted = true;
                    //MessageBox.Show("Image is splitted");
                }
                else
                {
                    //MessageBox.Show("Image is not splitted");
                    this.isSplitted = false;
                }
            }

            if (isCompressed)
            {
                this.WUDDiscReader = new WUDDiscReaderCompressed(this);
            }
            else if (isSplitted)
            {
                this.WUDDiscReader = new WUDDiscReaderSplitted(this);
            }
            else
            {
                this.WUDDiscReader = new WUDDiscReaderUncompressed(this);
            }

            fileStream.Close();
            this.fileHandle = file;
        }
示例#2
0
        public static FileInfo compressWUDToWUX(WUDImage image, String outputFolder, String filename, bool overwrite)
        {
            if (image.isCompressed)
            {
                //log.info("Given image is already compressed");
                return(null);
            }

            if (image.getWUDFileSize() != WUDImage.WUD_FILESIZE)
            {
                //log.info("Given WUD has not the expected filesize");
                return(null);
            }

            String usedOutputFolder = outputFolder;

            if (usedOutputFolder == null)
            {
                usedOutputFolder = "";
            }
            Utils.createDir(usedOutputFolder);

            String filePath;

            if (usedOutputFolder == String.Empty)
            {
                filePath = filename;
            }
            else
            {
                filePath = usedOutputFolder + Path.DirectorySeparatorChar + filename;
            }

            FileInfo outputFile = new FileInfo(filePath);

            if (outputFile.Exists && !overwrite)
            {
                //log.info("Couldn't compress wud, target file already exists (" + outputFile.getAbsolutePath() + ")");
                return(null);
            }

            //log.info("Writing compressed file to: " + outputFile.getAbsolutePath());
            FileStream   fileStream = new FileStream(outputFile.FullName, FileMode.Create);
            BinaryWriter fileOutput = new BinaryWriter(fileStream);

            WUDImageCompressedInfo info = WUDImageCompressedInfo.getDefaultCompressedInfo();

            byte[] header = info.getHeaderAsBytes();
            //log.info("Writing header");
            fileOutput.Write(header);

            int sectorTableEntryCount = (int)((image.getWUDFileSize() + WUDImageCompressedInfo.SECTOR_SIZE - 1) / (long)WUDImageCompressedInfo.SECTOR_SIZE);

            long sectorTableStart = fileOutput.BaseStream.Position;
            long sectorTableEnd   = Utils.align(sectorTableEntryCount * 0x04, WUDImageCompressedInfo.SECTOR_SIZE);

            byte[] sectorTablePlaceHolder = new byte[(int)(sectorTableEnd - sectorTableStart)];

            fileOutput.Write(sectorTablePlaceHolder);

            Dictionary <ByteArrayWrapper, int> sectorHashes = new Dictionary <ByteArrayWrapper, int>();
            Dictionary <int, int> sectorMapping             = new Dictionary <int, int>();

            MemoryStream min = image.WUDDiscReader.readEncryptedToInputStream(0, image.getWUDFileSize());

            int bufferSize = WUDImageCompressedInfo.SECTOR_SIZE;

            byte[]          blockBuffer = new byte[bufferSize];
            ByteArrayBuffer overflow    = new ByteArrayBuffer(bufferSize);

            long written    = 0;
            int  curSector  = 0;
            int  realSector = 0;

            //log.info("Writing sectors");

            Int32 oldOffset = int.MinValue;

            min.Seek(0, SeekOrigin.Begin);
            do
            {
                //int read = StreamUtils.getChunkFromStream(in, blockBuffer, overflow, bufferSize);
                int read = min.Read(blockBuffer, 0, bufferSize);
                ByteArrayWrapper hash = new ByteArrayWrapper(HashUtil.hashSHA1(blockBuffer));

                if (!sectorHashes.TryGetValue(hash, out oldOffset))
                {
                    sectorMapping.Add(curSector, realSector);
                    sectorHashes.Add(hash, realSector);
                    fileOutput.Write(blockBuffer);
                    realSector++;
                }
                else
                {
                    sectorMapping.Add(curSector, oldOffset);
                    oldOffset = int.MinValue;
                }

                written += read;
                curSector++;
                if (curSector % 10 == 0)
                {
                    double readMB    = written / 1024.0 / 1024.0;
                    double writtenMB = ((long)realSector * (long)bufferSize) / 1024.0 / 1024.0;
                    double percent   = ((double)written / image.getWUDFileSize()) * 100;
                    double ratio     = 1 / (writtenMB / readMB);
                    //System.out.print(String.format(Locale.ROOT, "\rCompressing into .wux | Progress %.2f%% | Ratio: 1:%.2f | Read: %.2fMB | Written: %.2fMB\t", percent, ratio, readMB, writtenMB));
                }
            } while (written < image.getWUDFileSize());
            //System.out.println();
            //System.out.println("Sectors compressed.");
            //log.info("Writing sector table");
            fileOutput.BaseStream.Seek(sectorTableStart, SeekOrigin.Begin);
            ByteBuffer buffer = ByteBuffer.allocate(sectorTablePlaceHolder.Length);

            //buffer.order(ByteOrder.LITTLE_ENDIAN);
            foreach (var e in sectorMapping)
            {
                buffer.putInt(e.Value);
            }

            fileOutput.Write(buffer.array());
            fileOutput.Close();

            return(outputFile);
        }
示例#3
0
        /**
         * Expects the .wux format by Exzap. You can more infos about it here. https://gbatemp.net/threads/wii-u-image-wud-compression-tool.397901/
         */
        public override void readEncryptedToOutputStream(Stream outputStream, long offset, long size)
        {
            // make sure there is no out-of-bounds read
            WUDImageCompressedInfo info = image.compressedInfo;

            long fileBytesLeft = info.uncompressedSize - offset;

            long usedOffset = offset;
            long usedSize   = size;

            if (fileBytesLeft <= 0)
            {
                //MessageBox.Show("offset too big");
                //System.exit(1);
                return;
            }
            if (fileBytesLeft < usedSize)
            {
                usedSize = fileBytesLeft;
            }
            // compressed read must be handled on a per-sector level

            int bufferSize = 0x8000;

            byte[] buffer = new byte[bufferSize];

            BinaryReader input = getRandomAccessFileStream();

            while (usedSize > 0)
            {
                long sectorOffset         = (usedOffset % info.sectorSize);
                long remainingSectorBytes = info.sectorSize - sectorOffset;
                long sectorIndex          = (usedOffset / info.sectorSize);
                int  bytesToRead          = (int)((remainingSectorBytes < usedSize) ? remainingSectorBytes : usedSize); // read only up to the end of the current sector
                // look up real sector index
                long realSectorIndex = info.getSectorIndex((int)sectorIndex);
                long offset2         = info.offsetSectorArray + realSectorIndex * info.sectorSize + sectorOffset;

                input.BaseStream.Seek(offset2, SeekOrigin.Begin);
                int read = input.Read(buffer, 0, buffer.Length);
                if (read < 0)
                {
                    return;
                }
                try
                {
                    outputStream.Write(buffer, 0, bytesToRead);
                }
                catch (Exception)
                {
                    //if (e.getMessage().equals("Pipe closed")) {
                    //    break;
                    //} else {
                    //    throw e;
                    //}
                }

                usedSize   -= bytesToRead;
                usedOffset += bytesToRead;
            }
            input.Close();
        }