示例#1
0
            public static PX0TrackHeader GetTrackHeader(byte[] dta, ref int pos)
            {
                if (pos >= dta.Length)
                {
                    return(null);
                }

                var hdr = new PX0TrackHeader(dta[pos], dta[pos + 1], dta[pos + 2], dta[pos + 3], dta[pos + 4]);
                var crc = (byte)(GetCRC(dta, pos, 4, 0) & 0xff);

                if (crc != hdr.CRC && hdr.NumberOfSectors != 255)
                {
                    throw new Exception("Track Header CRC is invalid!");
                }

                pos += 4; // On last byte of track header

                return(hdr);
            }
示例#2
0
        // Example input (from DOS prompt)
        // ExtractPX0.exe "D:\Applications\APPRO6.2.27.167\OrigPickFiles\35.datafiles1.px0"
        static void Main(string[] args)
        {
            string inPath = (null == args || 1 != args.Length || null == args[0]) ? null : args[0].Trim();

            if (string.IsNullOrEmpty(inPath))
            {
                // We were expecting only a single parameter..
                ShowUsage();
                return;
            }

            var fi = new FileInfo(inPath);

            if (!fi.Exists)
            {
                // Parameter does not represent a file
                Console.WriteLine("File not found! '{0}'", inPath);
                return;
            }
            if (0 != string.Compare(fi.Extension, ".px0", true))
            {
                // Input files are expected to have a '.px0' extension!
                Console.WriteLine("Not a '.px0' file! '{0}'", inPath);
                return;
            }

            string outPath = Path.ChangeExtension(fi.FullName, ".img");

            if (File.Exists(outPath))
            {
                // Do not overwrite existing '.img' files!
                Console.WriteLine("Output file already exists! '{0}'", outPath);
                return;
            }

            var sectorDataList = new List <SectorData>();

            try
            {
                // Get PXO file bytes. If compressed data existed, these bytes will
                // represent the decompressed form!
                var px0Bytes = GetPX0ImageBytes(inPath);

                // Init a pointer we will use to traverse the PX0 file byte array
                var px0Ptr = 0;

                // Check that bytes represent valid data, read file header structure.
                var px0Hdr = PX0Header.GetHeader(px0Bytes, ref px0Ptr);
                px0Ptr++; // On first byte *after* header

                PX0CommentHeader px0CmtHdr = null;
                if ((px0Hdr.Stepping & 0x80) != 0)
                {
                    // Extract 'comment header'
                    px0CmtHdr = PX0CommentHeader.GetCommentHeader(px0Bytes, ref px0Ptr);
                    px0Ptr++; // On first byte *after* 'comment header'
                }

                // Loop over track headers
                PX0TrackHeader trkHdr;
                while ((trkHdr = PX0TrackHeader.GetTrackHeader(px0Bytes, ref px0Ptr)) != null)
                {
                    if (trkHdr.NumberOfSectors == 255)
                    {
                        break; // EOF marker!
                    }
                    px0Ptr++;  // On first byte *after* 'track header'
                    for (int sNo = 0; sNo < trkHdr.NumberOfSectors; sNo++)
                    {
                        var sectHeader = PX0SectorHeader.GetSectorHeader(px0Bytes, ref px0Ptr);

                        /*
                         * Calculate 'Logical Sector' number (from: http://stackoverflow.com/questions/5774164/lba-and-cluster or
                         * http://en.wikipedia.org/wiki/Cylinder-head-sector)
                         * There are many sector numbering schemes on disk drives. One of the earliest was CHS (Cylinder-Head-Sector).
                         * One sector can be selected by specifying the cylinder (track), read/write head and sector per track triplet.
                         * This numbering scheme depends on the actual physical characteristics of the disk drive.
                         * The first logical sector resides on cylinder 0, head 0, sector 1. The second is on sector 2, and so on.
                         * If there isn't any more sectors on the disk (eg. on a 1.44M floppy disk there's 18 sectors per track),
                         * then the next head is applied, starting on sector 1 again, and so on.
                         *
                         * You can convert CHS addresses to an absolute (or logical) sector number with a little math:
                         *
                         * LSN = (C * Nh + H) * Ns + S - 1
                         *
                         * where C, H and S are the cylinder, head and sector numbers according to CHS adressing, while Nh and Ns are
                         * the number of heads and number of sectors per track (cylinder), respectively.
                         *
                         * To convert a logical sector number into a cylinder, head and sector number:
                         * S = (LSN mod Ns) + 1
                         * H = (LSN / Ns) mod Nh
                         * C = LSN / (Ns * Nh)
                         */

                        var LSN = (trkHdr.CylNumber * px0Hdr.Sides + trkHdr.SideHeadNumber)
                                  * trkHdr.NumberOfSectors + sectHeader.SectorNumber - 1;

                        //System.Diagnostics.Debug.WriteLine(string.Format("LSN = {0} where: C: {1}, Nh: {2}, H: {3}, Ns: {4}, S: {5}",
                        //    LSN, trkHdr.CylNumber, px0Hdr.Sides, trkHdr.SideHeadNumber, trkHdr.NumberOfCylinders, sectHeader.SectorNumber));

                        sectorDataList.Add(new SectorData(LSN, sectHeader.sDta));
                        px0Ptr++; // On first byte *after* 'sector header'
                    }
                }
                if (sectorDataList.Count < 1)
                {
                    throw new Exception("No sector data extracted!");
                }

                // Sort sector data by 'logical sector number'
                sectorDataList.Sort();
            }
            catch (Exception ex)
            {
                Console.WriteLine("*ERROR* - Failed to convert file '{0}' - error: '{1}'", inPath, ex.Message);

                return;
            }

            // Write out the image file!
            try
            {
                using (var binWriter =
                           new BinaryWriter(File.Open(outPath, FileMode.Create)))
                {
                    // Write out the disk image!!
                    foreach (var td in sectorDataList)
                    {
                        binWriter.Write(td.dta);
                    }
                    binWriter.Flush();
                }
                Console.WriteLine("Finished writing image file: " + outPath);
            }
            catch (Exception ex)
            {
                Console.WriteLine("*ERROR* - Failed to write image file '{0}' - error: '{1}'", outPath, ex.Message);
            }
        }