コード例 #1
0
            public static PX0CommentHeader GetCommentHeader(byte[] dta, ref int pos)
            {
                var dlen   = (ushort)(dta[pos + 3] << 8 | dta[pos + 2]);
                var cBytes = new byte[dlen];

                for (var i = 0; i < dlen; i++)
                {
                    byte b = dta[pos + 10 + i];
                    if (b == 0)
                    {
                        b = (byte)'\n';
                    }

                    cBytes[i] = b;
                }

                var hdr = new PX0CommentHeader(
                    (ushort)(dta[pos + 1] << 8 | dta[pos]), dlen,
                    dta[pos + 4], dta[pos + 5], dta[pos + 6], dta[pos + 7], dta[pos + 8], dta[pos + 9],
                    Encoding.ASCII.GetString(cBytes, 0, dlen)
                    );

                var crc = GetCRC(dta, pos + 2, 8 + dlen, 0);

                if (crc != hdr.CRC)
                {
                    throw new Exception("Comment Header CRC is invalid!");
                }

                pos += (dlen + 9); // On last byte of comment 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);
            }
        }