Esempio n. 1
0
        public static void UpdateBootstrapTableOfContents(byte[] bootstrapData, List <GDTrack> tracks)
        {
            //Tracks 03 to 99, 1 and 2 were in the low density area
            for (int t = 0; t < 97; t++)
            {
                uint dcLBA  = 0xFFFFFF;
                byte dcType = 0xFF;
                if (t < tracks.Count)
                {
                    GDTrack track = tracks[t];
                    dcLBA  = track.LBA + 150;
                    dcType = (byte)(((uint)track.Type << 4) | 0x1);
                }
                int offset = 0x104 + (t * 4);
                bootstrapData[offset++] = (byte)(dcLBA & 0xFF);
                bootstrapData[offset++] = (byte)((dcLBA >> 8) & 0xFF);
                bootstrapData[offset++] = (byte)((dcLBA >> 16) & 0xFF);
                bootstrapData[offset]   = dcType;
            }

            // Update track count in bootsector (HDA + SDA tracks count)
            bootstrapData[0x28E] = (byte)(tracks.Count + 2);
        }
Esempio n. 2
0
        private List <GDTrack> ReadCDDA(List <string> gdda)
        {
            List <GDTrack> retval = new List <GDTrack>();

            foreach (string path in gdda)
            {
                FileInfo fi = new FileInfo(path);
                if (!fi.Exists)
                {
                    throw new FileNotFoundException("GDDA track " + fi.Name + " could not be accessed.");
                }

                GDTrack track = new GDTrack
                {
                    FileName = fi.Name,
                    Type     = 0,
                    FileSize = fi.Length
                };

                retval.Add(track);
            }

            return(retval);
        }
Esempio n. 3
0
        private void WriteDataTrack(bool isSingleDensityArea, BuiltStream isoStream, byte[] bootstrapData, List <GDTrack> tracks)
        {
            // When starting this, tracks contains only GDDA tracks (for SDA: only 1 audio track, for HDA: all GDDA if any)

            long currentBytes = 0;
            long totalBytes   = isoStream.Length;
            int  skip         = 0;
            int  currentLBA   = isSingleDensityArea ? SINGLE_DENSITY_AREA_LBA_START : HIGH_DENSITY_AREA_LBA_START;

            bool isHighDensityAreaMultiDataTrack = !isSingleDensityArea && HighDensityDataTrackSplitted;

            string dataTrackFileFirstPath = isSingleDensityArea ? _singleDensityAreaDataTrackPath : _highDensityAreaDataTrackFirstPath; // for SDA/HDA
            string dataTrackFileLastPath  = isSingleDensityArea ? string.Empty : _highDensityAreaDataTrackLastPath;                     // for HDA only

            // Retrive the real space occuped on the data track
            long lastHeaderEnd  = 0;
            long firstFileStart = 0;

            foreach (BuilderExtent extent in isoStream.BuilderExtents)
            {
                if (extent is FileExtent)
                {
                    firstFileStart = extent.Start;
                    break;
                }
                else
                {
                    lastHeaderEnd = extent.Start + GDImageUtility.RoundUp(extent.Length, DATA_SECTOR_SIZE);
                }
            }
            lastHeaderEnd  /= DATA_SECTOR_SIZE;
            firstFileStart /= DATA_SECTOR_SIZE;

            // HDA: Single track is filling all the available space by default, if only one data track in HDA (computed below if HDA has GDDA)
            int trackEnd = HIGH_DENSITY_AREA_LBA_END - HIGH_DENSITY_AREA_LBA_START;

            // SDA: Computing trackEnd for the data track
            if (isSingleDensityArea)
            {
                // SDA: Single data track (track01) is filling the available space... after taken into account the SDA audio track
                long singleDensityAreaAudioTrackFileSize = tracks[0].FileSize; // When SDA, tracks[0] = SDA Audio Track (only 1 track)

                // Computing the space filled by the SDA audio track
                int singleDensityAreaAudioTrackSectorsSize = (int)(GDImageUtility.RoundUp(singleDensityAreaAudioTrackFileSize, RAW_SECTOR_SIZE) / RAW_SECTOR_SIZE);

                // So the SDA data track will fill this space...
                trackEnd = SINGLE_DENSITY_AREA_LBA_END - singleDensityAreaAudioTrackSectorsSize - TRACK_GAP_SECTOR_COUNT; /* FIXME */

                // Updating the SDA audio track in consequence
                tracks[0].LBA = (uint)trackEnd + TRACK_GAP_SECTOR_COUNT;
            }

            if (isHighDensityAreaMultiDataTrack)
            {
                trackEnd = RecomputeAudioTracksLogicalBlockAddresses(tracks, HIGH_DENSITY_AREA_LBA_START, firstFileStart);

                if (trackEnd < lastHeaderEnd)
                {
                    throw new Exception("Not enough room to fit all of the CDDA after we added the data.");
                }

                // trackEnd: HDA when multi tracks: computed with GDDA
            }

            long firstTrackFileSize = trackEnd * DATA_SECTOR_SIZE;

            // Applied for SDA data track and HDA first data track
            if (TruncateData)
            {
                long firstTrackSectorSize = (lastHeaderEnd > TRACK_MINIMUM_SECTOR_COUNT ? lastHeaderEnd : TRACK_MINIMUM_SECTOR_COUNT);
                RecomputeAudioTracksLogicalBlockAddresses(tracks, (uint)currentLBA, firstTrackSectorSize);
                firstTrackFileSize = firstTrackSectorSize * DATA_SECTOR_SIZE;
            }

            // Handle data track (SDA is track01, HDA is track03)
            GDTrack firstTrack = new GDTrack
            {
                FileName = Path.GetFileName(dataTrackFileFirstPath),
                FileSize = firstTrackFileSize,
                LBA      = (uint)currentLBA,
                Type     = GDTrackType.Data
            };

            tracks.Insert(0, firstTrack); // the first data track is at the beginning of the area

            // Handle last data track for HDA (if applicable)
            GDTrack lastTrack = null;

            if (isHighDensityAreaMultiDataTrack)
            {
                lastTrack = new GDTrack
                {
                    FileName = Path.GetFileName(dataTrackFileLastPath),
                    FileSize = (HIGH_DENSITY_AREA_LBA_END - HIGH_DENSITY_AREA_LBA_START - firstFileStart) * DATA_SECTOR_SIZE,
                    LBA      = (uint)(HIGH_DENSITY_AREA_LBA_START + firstFileStart),
                    Type     = GDTrackType.Data
                };
                tracks.Add(lastTrack);
            }

            // Update the TOC in the IP.BIN for the HDA
            if (!isSingleDensityArea)
            {
                GDImageUtility.UpdateBootstrapTableOfContents(bootstrapData, tracks);
            }

            // Initialize stream variables
            byte[] buffer       = new byte[DATA_SECTOR_SIZE];
            int    numRead      = 0;
            long   bytesWritten = 0;

            // Write first (or single) data track
            using (FileStream destStream = new FileStream(dataTrackFileFirstPath, FileMode.Create, FileAccess.Write))
            {
                // Write Bootsector data in the first sector
                bytesWritten = GDImageWriteHelper.WriteBootSector(RawMode, isoStream, destStream, buffer, ref currentLBA, ref currentBytes, bootstrapData);

                numRead = isoStream.Read(buffer, 0, buffer.Length);
                while (numRead != 0 && bytesWritten < firstTrack.FileSize)
                {
                    GDImageWriteHelper.WriteSector(RawMode, isoStream, destStream, buffer, ref currentLBA, ref numRead);

                    numRead       = isoStream.Read(buffer, 0, buffer.Length);
                    bytesWritten += numRead;
                    currentBytes += numRead;

                    skip = NotifyProgress(currentBytes, totalBytes, skip);
                }
            }

            // Write last data track (if any)
            if (isHighDensityAreaMultiDataTrack)
            {
                currentLBA = (int)lastTrack.LBA;

                using (FileStream destStream = new FileStream(dataTrackFileLastPath, FileMode.Create, FileAccess.Write))
                {
                    currentBytes = firstFileStart * DATA_SECTOR_SIZE;
                    isoStream.Seek(currentBytes, SeekOrigin.Begin);

                    numRead = isoStream.Read(buffer, 0, buffer.Length);
                    while (numRead != 0)
                    {
                        GDImageWriteHelper.WriteSector(RawMode, isoStream, destStream, buffer, ref currentLBA, ref numRead);

                        numRead       = isoStream.Read(buffer, 0, buffer.Length);
                        currentBytes += numRead;

                        skip = NotifyProgress(currentBytes, totalBytes, skip);
                    }
                }
            }
        }