コード例 #1
0
        /// <summary>
        /// Attempts to parse incoming disk data
        /// </summary>
        /// <param name="diskData"></param>
        /// <returns>
        /// TRUE:   disk parsed
        /// FALSE:  unable to parse disk
        /// </returns>
        public override bool ParseDisk(byte[] data)
        {
            // look for standard magic string
            string ident = Encoding.ASCII.GetString(data, 0, 16);

            if (!ident.ToUpper().Contains("MV - CPC"))
            {
                // incorrect format
                return(false);
            }

            // read the disk information block
            DiskHeader.DiskIdent         = ident;
            DiskHeader.DiskCreatorString = Encoding.ASCII.GetString(data, 0x22, 14);
            DiskHeader.NumberOfTracks    = data[0x30];
            DiskHeader.NumberOfSides     = data[0x31];
            DiskHeader.TrackSizes        = new int[DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides];
            DiskTracks = new Track[DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides];
            DiskData   = data;
            int pos = 0x32;

            if (DiskHeader.NumberOfSides > 1)
            {
                StringBuilder sbm = new StringBuilder();
                sbm.AppendLine();
                sbm.AppendLine();
                sbm.AppendLine("The detected disk image contains multiple sides.");
                sbm.AppendLine("This is NOT currently supported in ZXHawk.");
                sbm.AppendLine("Please find an alternate image/dump where each side has been saved as a separate *.dsk image (and use the mutli-disk bundler tool to load into Bizhawk).");
                throw new System.NotImplementedException(sbm.ToString());
            }

            // standard CPC format all track sizes are the same in the image
            for (int i = 0; i < DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides; i++)
            {
                DiskHeader.TrackSizes[i] = MediaConverter.GetWordValue(data, pos);
            }

            // move to first track information block
            pos = 0x100;

            // parse each track
            for (int i = 0; i < DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides; i++)
            {
                // check for unformatted track
                if (DiskHeader.TrackSizes[i] == 0)
                {
                    DiskTracks[i]         = new Track();
                    DiskTracks[i].Sectors = new Sector[0];
                    continue;
                }

                int p = pos;
                DiskTracks[i] = new Track();

                // track info block
                DiskTracks[i].TrackIdent = Encoding.ASCII.GetString(data, p, 12);
                p += 16;
                DiskTracks[i].TrackNumber = data[p++];
                DiskTracks[i].SideNumber  = data[p++];
                p += 2;
                DiskTracks[i].SectorSize      = data[p++];
                DiskTracks[i].NumberOfSectors = data[p++];
                DiskTracks[i].GAP3Length      = data[p++];
                DiskTracks[i].FillerByte      = data[p++];

                int dpos = pos + 0x100;

                // sector info list
                DiskTracks[i].Sectors = new Sector[DiskTracks[i].NumberOfSectors];
                for (int s = 0; s < DiskTracks[i].NumberOfSectors; s++)
                {
                    DiskTracks[i].Sectors[s] = new Sector();

                    DiskTracks[i].Sectors[s].TrackNumber          = data[p++];
                    DiskTracks[i].Sectors[s].SideNumber           = data[p++];
                    DiskTracks[i].Sectors[s].SectorID             = data[p++];
                    DiskTracks[i].Sectors[s].SectorSize           = data[p++];
                    DiskTracks[i].Sectors[s].Status1              = data[p++];
                    DiskTracks[i].Sectors[s].Status2              = data[p++];
                    DiskTracks[i].Sectors[s].ActualDataByteLength = MediaConverter.GetWordValue(data, p);
                    p += 2;

                    // actualdatabytelength value is calculated now
                    if (DiskTracks[i].Sectors[s].SectorSize == 0)
                    {
                        // no sectorsize specified - DTL will be used at runtime
                        DiskTracks[i].Sectors[s].ActualDataByteLength = DiskHeader.TrackSizes[i];
                    }
                    else if (DiskTracks[i].Sectors[s].SectorSize > 6)
                    {
                        // invalid - wrap around to 0
                        DiskTracks[i].Sectors[s].ActualDataByteLength = DiskHeader.TrackSizes[i];
                    }
                    else if (DiskTracks[i].Sectors[s].SectorSize == 6)
                    {
                        // only 0x1800 bytes are stored
                        DiskTracks[i].Sectors[s].ActualDataByteLength = 0x1800;
                    }
                    else
                    {
                        // valid sector size for this format
                        DiskTracks[i].Sectors[s].ActualDataByteLength = 0x80 << DiskTracks[i].Sectors[s].SectorSize;
                    }

                    // sector data - begins at 0x100 offset from the start of the track info block (in this case dpos)
                    DiskTracks[i].Sectors[s].SectorData = new byte[DiskTracks[i].Sectors[s].ActualDataByteLength];

                    // copy the data
                    for (int b = 0; b < DiskTracks[i].Sectors[s].ActualDataByteLength; b++)
                    {
                        DiskTracks[i].Sectors[s].SectorData[b] = data[dpos + b];
                    }

                    // move dpos to the next sector data postion
                    dpos += DiskTracks[i].Sectors[s].ActualDataByteLength;
                }

                // move to the next track info block
                pos += DiskHeader.TrackSizes[i];
            }

            // run protection scheme detector
            ParseProtection();

            return(true);
        }
コード例 #2
0
        /// <summary>
        /// Takes a double-sided disk byte array and converts into 2 single-sided arrays
        /// </summary>
        /// <param name="data"></param>
        /// <param name="results"></param>
        /// <returns></returns>
        public static bool SplitDoubleSided(byte[] data, List <byte[]> results)
        {
            // look for standard magic string
            string ident = Encoding.ASCII.GetString(data, 0, 4);

            if (!ident.StartsWith("UDI!") && !ident.StartsWith("udi!"))
            {
                // incorrect format
                return(false);
            }

            if (data[0x08] != 0)
            {
                // wrong version
                return(false);
            }

            if (ident == "udi!")
            {
                // cant handle compression yet
                return(false);
            }

            byte[] S0 = new byte[data.Length];
            byte[] S1 = new byte[data.Length];

            // header
            var extHdr = MediaConverter.GetInt32(data, 0x0C);

            Array.Copy(data, 0, S0, 0, 0x10 + extHdr);
            Array.Copy(data, 0, S1, 0, 0x10 + extHdr);
            // change side number
            S0[0x0A] = 0;
            S1[0x0A] = 0;

            int pos      = 0x10 + extHdr;
            int fileSize = MediaConverter.GetInt32(data, 4); // not including the final 4-byte checksum

            int s0Pos = pos;
            int s1Pos = pos;

            // process track information
            for (int t = 0; t < (data[0x09] + 1) * 2; t++)
            {
                var TLEN      = MediaConverter.GetWordValue(data, pos + 1);
                var CLEN      = TLEN / 8 + (TLEN % 8 / 7) / 8;
                var blockSize = TLEN + CLEN + 3;

                // 2 sided image: side 0 tracks will all have t as an even number
                try
                {
                    if (t == 0 || t % 2 == 0)
                    {
                        Array.Copy(data, pos, S0, s0Pos, blockSize);
                        s0Pos += blockSize;
                    }
                    else
                    {
                        Array.Copy(data, pos, S1, s1Pos, blockSize);
                        s1Pos += blockSize;
                    }
                }
                catch (Exception ex)
                {
                }


                pos += blockSize;
            }

            // skip checkum bytes for now

            byte[] s0final = new byte[s0Pos];
            byte[] s1final = new byte[s1Pos];
            Array.Copy(S0, 0, s0final, 0, s0Pos);
            Array.Copy(S1, 0, s1final, 0, s1Pos);

            results.Add(s0final);
            results.Add(s1final);

            return(true);
        }
コード例 #3
0
ファイル: CPCFloppyDisk.cs プロジェクト: sornerol/BizHawk
        /// <summary>
        /// Takes a double-sided disk byte array and converts into 2 single-sided arrays
        /// </summary>
        public static bool SplitDoubleSided(byte[] data, List <byte[]> results)
        {
            // look for standard magic string
            string ident = Encoding.ASCII.GetString(data, 0, 16);

            if (!ident.ToUpper().Contains("MV - CPC"))
            {
                // incorrect format
                return(false);
            }

            byte[] S0 = new byte[data.Length];
            byte[] S1 = new byte[data.Length];

            // disk info block
            Array.Copy(data, 0, S0, 0, 0x100);
            Array.Copy(data, 0, S1, 0, 0x100);
            // change side number
            S0[0x31] = 1;
            S1[0x31] = 1;

            var trkSize = MediaConverter.GetWordValue(data, 0x32);

            // start at track info blocks
            int mPos  = 0x100;
            int s0Pos = 0x100;
            int s1Pos = 0x100;

            var numTrks  = data[0x30];
            var numSides = data[0x31];

            while (mPos < trkSize * data[0x30] * data[0x31])
            {
                // which side is this?
                var side = data[mPos + 0x11];
                if (side == 0)
                {
                    // side 1
                    Array.Copy(data, mPos, S0, s0Pos, trkSize);
                    s0Pos += trkSize;
                }
                else if (side == 1)
                {
                    // side 2
                    Array.Copy(data, mPos, S1, s1Pos, trkSize);
                    s1Pos += trkSize;
                }
                else
                {
                }

                mPos += trkSize;
            }

            byte[] s0final = new byte[s0Pos];
            byte[] s1final = new byte[s1Pos];
            Array.Copy(S0, 0, s0final, 0, s0Pos);
            Array.Copy(S1, 0, s1final, 0, s1Pos);

            results.Add(s0final);
            results.Add(s1final);

            return(true);
        }
コード例 #4
0
        /// <summary>
        /// Attempts to parse incoming disk data
        /// </summary>
        /// <returns>
        /// TRUE:   disk parsed
        /// FALSE:  unable to parse disk
        /// </returns>
        public override bool ParseDisk(byte[] data)
        {
            // look for standard magic string
            string ident = Encoding.ASCII.GetString(data, 0, 16);

            if (!ident.ToUpper().Contains("EXTENDED CPC DSK"))
            {
                // incorrect format
                return(false);
            }

            // read the disk information block
            DiskHeader.DiskIdent         = ident;
            DiskHeader.DiskCreatorString = Encoding.ASCII.GetString(data, 0x22, 14);
            DiskHeader.NumberOfTracks    = data[0x30];
            DiskHeader.NumberOfSides     = data[0x31];
            DiskHeader.TrackSizes        = new int[DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides];
            DiskTracks = new Track[DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides];
            DiskData   = data;
            int pos = 0x34;

            if (DiskHeader.NumberOfSides > 1)
            {
                StringBuilder sbm = new StringBuilder();
                sbm.AppendLine();
                sbm.AppendLine();
                sbm.AppendLine("The detected disk image contains multiple sides.");
                sbm.AppendLine("This is NOT currently supported in ZXHawk.");
                sbm.AppendLine("Please find an alternate image/dump where each side has been saved as a separate *.dsk image (and use the multi-disk bundler tool to load into Bizhawk).");
                throw new System.NotImplementedException(sbm.ToString());
            }

            if (DiskHeader.NumberOfTracks > 42)
            {
                StringBuilder sbm = new StringBuilder();
                sbm.AppendLine();
                sbm.AppendLine();
                sbm.AppendLine("The detected disk is an " + DiskHeader.NumberOfTracks + " track disk image.");
                sbm.AppendLine("This is currently incompatible with the emulated +3 disk drive (42 tracks).");
                sbm.AppendLine("Likely the disk image is an 80 track betadisk or opus image, the drives and controllers for which are not currently emulated in ZXHawk");
                throw new System.NotImplementedException(sbm.ToString());
            }

            for (int i = 0; i < DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides; i++)
            {
                DiskHeader.TrackSizes[i] = data[pos++] * 256;
            }

            // move to first track information block
            pos = 0x100;

            // parse each track
            for (int i = 0; i < DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides; i++)
            {
                // check for unformatted track
                if (DiskHeader.TrackSizes[i] == 0)
                {
                    DiskTracks[i]         = new Track();
                    DiskTracks[i].Sectors = new Sector[0];
                    continue;
                }

                int p = pos;
                DiskTracks[i] = new Track();

                // track info block
                DiskTracks[i].TrackIdent = Encoding.ASCII.GetString(data, p, 12);
                p += 16;
                DiskTracks[i].TrackNumber     = data[p++];
                DiskTracks[i].SideNumber      = data[p++];
                DiskTracks[i].DataRate        = data[p++];
                DiskTracks[i].RecordingMode   = data[p++];
                DiskTracks[i].SectorSize      = data[p++];
                DiskTracks[i].NumberOfSectors = data[p++];
                DiskTracks[i].GAP3Length      = data[p++];
                DiskTracks[i].FillerByte      = data[p++];

                int dpos = pos + 0x100;

                // sector info list
                DiskTracks[i].Sectors = new Sector[DiskTracks[i].NumberOfSectors];
                for (int s = 0; s < DiskTracks[i].NumberOfSectors; s++)
                {
                    DiskTracks[i].Sectors[s] = new Sector();

                    DiskTracks[i].Sectors[s].TrackNumber          = data[p++];
                    DiskTracks[i].Sectors[s].SideNumber           = data[p++];
                    DiskTracks[i].Sectors[s].SectorID             = data[p++];
                    DiskTracks[i].Sectors[s].SectorSize           = data[p++];
                    DiskTracks[i].Sectors[s].Status1              = data[p++];
                    DiskTracks[i].Sectors[s].Status2              = data[p++];
                    DiskTracks[i].Sectors[s].ActualDataByteLength = MediaConverter.GetWordValue(data, p);
                    p += 2;

                    // sector data - begins at 0x100 offset from the start of the track info block (in this case dpos)
                    DiskTracks[i].Sectors[s].SectorData = new byte[DiskTracks[i].Sectors[s].ActualDataByteLength];

                    // copy the data
                    for (int b = 0; b < DiskTracks[i].Sectors[s].ActualDataByteLength; b++)
                    {
                        DiskTracks[i].Sectors[s].SectorData[b] = data[dpos + b];
                    }

                    // check for multiple weak/random sectors stored
                    if (DiskTracks[i].Sectors[s].SectorSize <= 7)
                    {
                        // sectorsize n=8 is equivilent to n=0 - FDC will use DTL for length
                        int specifiedSize = 0x80 << DiskTracks[i].Sectors[s].SectorSize;

                        if (specifiedSize < DiskTracks[i].Sectors[s].ActualDataByteLength)
                        {
                            // more data stored than sectorsize defines
                            // check for multiple weak/random copies
                            if (DiskTracks[i].Sectors[s].ActualDataByteLength % specifiedSize != 0)
                            {
                                DiskTracks[i].Sectors[s].ContainsMultipleWeakSectors = true;
                            }
                        }
                    }

                    // move dpos to the next sector data postion
                    dpos += DiskTracks[i].Sectors[s].ActualDataByteLength;
                }

                // move to the next track info block
                pos += DiskHeader.TrackSizes[i];
            }

            // run protection scheme detector
            ParseProtection();

            return(true);
        }
コード例 #5
0
        /// <summary>
        /// Attempts to parse incoming disk data
        /// </summary>
        /// <param name="diskData"></param>
        /// <returns>
        /// TRUE:   disk parsed
        /// FALSE:  unable to parse disk
        /// </returns>
        public override bool ParseDisk(byte[] data)
        {
            // look for standard magic string
            string ident = Encoding.ASCII.GetString(data, 0, 16);

            if (!ident.ToUpper().Contains("EXTENDED CPC DSK"))
            {
                // incorrect format
                return(false);
            }

            // read the disk information block
            DiskHeader.DiskIdent         = ident;
            DiskHeader.DiskCreatorString = Encoding.ASCII.GetString(data, 0x22, 14);
            DiskHeader.NumberOfTracks    = data[0x30];
            DiskHeader.NumberOfSides     = data[0x31];
            DiskHeader.TrackSizes        = new int[DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides];
            DiskTracks = new Track[DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides];
            DiskData   = data;
            int pos = 0x34;

            for (int i = 0; i < DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides; i++)
            {
                DiskHeader.TrackSizes[i] = data[pos++] * 256;
            }

            // move to first track information block
            pos = 0x100;

            // parse each track
            for (int i = 0; i < DiskHeader.NumberOfTracks * DiskHeader.NumberOfSides; i++)
            {
                // check for unformatted track
                if (DiskHeader.TrackSizes[i] == 0)
                {
                    DiskTracks[i]         = new Track();
                    DiskTracks[i].Sectors = new Sector[0];
                    continue;
                }

                int p = pos;
                DiskTracks[i] = new Track();

                // track info block
                DiskTracks[i].TrackIdent = Encoding.ASCII.GetString(data, p, 12);
                p += 16;
                DiskTracks[i].TrackNumber     = data[p++];
                DiskTracks[i].SideNumber      = data[p++];
                DiskTracks[i].DataRate        = data[p++];
                DiskTracks[i].RecordingMode   = data[p++];
                DiskTracks[i].SectorSize      = data[p++];
                DiskTracks[i].NumberOfSectors = data[p++];
                DiskTracks[i].GAP3Length      = data[p++];
                DiskTracks[i].FillerByte      = data[p++];

                int dpos = pos + 0x100;

                // sector info list
                DiskTracks[i].Sectors = new Sector[DiskTracks[i].NumberOfSectors];
                for (int s = 0; s < DiskTracks[i].NumberOfSectors; s++)
                {
                    DiskTracks[i].Sectors[s] = new Sector();

                    DiskTracks[i].Sectors[s].TrackNumber          = data[p++];
                    DiskTracks[i].Sectors[s].SideNumber           = data[p++];
                    DiskTracks[i].Sectors[s].SectorID             = data[p++];
                    DiskTracks[i].Sectors[s].SectorSize           = data[p++];
                    DiskTracks[i].Sectors[s].Status1              = data[p++];
                    DiskTracks[i].Sectors[s].Status2              = data[p++];
                    DiskTracks[i].Sectors[s].ActualDataByteLength = MediaConverter.GetWordValue(data, p);
                    p += 2;

                    // sector data - begins at 0x100 offset from the start of the track info block (in this case dpos)
                    DiskTracks[i].Sectors[s].SectorData = new byte[DiskTracks[i].Sectors[s].ActualDataByteLength];

                    // copy the data
                    for (int b = 0; b < DiskTracks[i].Sectors[s].ActualDataByteLength; b++)
                    {
                        DiskTracks[i].Sectors[s].SectorData[b] = data[dpos + b];
                    }

                    // check for multiple weak/random sectors stored
                    if (DiskTracks[i].Sectors[s].SectorSize <= 7)
                    {
                        // sectorsize n=8 is equivilent to n=0 - FDC will use DTL for length
                        int specifiedSize = 0x80 << DiskTracks[i].Sectors[s].SectorSize;

                        if (specifiedSize < DiskTracks[i].Sectors[s].ActualDataByteLength)
                        {
                            // more data stored than sectorsize defines
                            // check for multiple weak/random copies
                            if (DiskTracks[i].Sectors[s].ActualDataByteLength % specifiedSize != 0)
                            {
                                DiskTracks[i].Sectors[s].ContainsMultipleWeakSectors = true;
                            }
                        }
                    }

                    // move dpos to the next sector data postion
                    dpos += DiskTracks[i].Sectors[s].ActualDataByteLength;
                }

                // move to the next track info block
                pos += DiskHeader.TrackSizes[i];
            }

            // run protection scheme detector
            ParseProtection();

            return(true);
        }