// ************** Extract File CP/M ********************* // inputs: path and filename, disk entry structure // output: requested file public int ExtractFileCPM(Form1.DiskFileEntry disk_file_entry) { var disk_image_file = disk_file_entry.DiskImageName; var result = 1; // assume success int temp; var diskType = 0; var ctr = 0; // for loop counter var maxBuffSize = 0x800; // largest allocation block size int allocBlock = 0, dirStart = 0, dirSize = 0, interleave = 0, spt = 0, sectorSize = 0; // disk parameter values var buff = new byte[maxBuffSize]; // disk buffer equal to largest allocation block size var wBuff = new byte[maxBuffSize]; // write buffer //var directory = new List<FCBlist>(); var skewMap = new int[16, 2]; // max number of sectors on a Heathkit floppy. Fill must be greater than buffer size for (var i = 0; i < 16; i++) // initialize skew table { skewMap[i, 0] = 32; skewMap[i, 1] = i; } // debug // var cpmFile = new CPMFile(); //var temp1 = FCBfirst.Count; var encoding = new UTF8Encoding(); var dir = string.Format("{0}_Files", disk_image_file); // create directory name and check if directory exists if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } fnameb = encoding.GetBytes(disk_file_entry.FileName); // Create output File var name = disk_file_entry.FileName.Substring(0, 8).Trim(' '); var ext = disk_file_entry.FileName.Substring(8, 3).Trim(' '); var file_name = string.Format("{0}\\{1}.{2}", dir, name, ext); if (File.Exists(file_name)) { if (MessageBox.Show("File exists, Overwrite it?", "File Exists", MessageBoxButtons.YesNo) == DialogResult.No) { result = 0; return(result); } else { file_name = file_name + "1"; } } var file_out = File.Create(file_name); var bin_out = new BinaryWriter(file_out); // Open input file var file = File.OpenRead(disk_image_file); var bin_file = new BinaryReader(file); temp = bin_file.Read(buff, 0, 256); var t = buff.Length; diskType = (int)buff[5]; /* debug * ctr = DiskType.GetLength(0); * ctr = DiskType.GetLength(1); */ for (ctr = 0; ctr < DiskType.GetLength(0); ctr++) // search DiskType array for values { if (diskType == DiskType[ctr, 0]) { break; } } // use default if no match found if (ctr == DiskType.GetLength(0)) { ctr = DiskType.GetLength(0) - 1; // default H17 format } allocBlock = DiskType[ctr, 1]; // ALB Size dirStart = DiskType[ctr, 2]; // physical start of directory dirSize = DiskType[ctr, 4]; // size of the directory interleave = DiskType[ctr, 5]; // disk interleave spt = DiskType[ctr, 6]; // sectors per track sectorSize = DiskType[ctr, 7]; // sector size //else // read the directory BuildSkew(ref skewMap, interleave, spt); // read directory sectors and place in sequential order in buff for (var i = 0; i < dirSize / allocBlock; i++) { GetALB(ref buff, allocBlock * i, bin_file, i, dirStart, allocBlock, sectorSize, spt, skewMap); } BuildDir(ref buff, dirSize, ref FCBfirst, fnameb); // build FCB list for filename foreach (var f in FCBfirst) { var fcbNum = f.fcbnum; var cpmAlb = allocBlock / 128; // number of 128 byte CP/M records in the allocation block var rBptr = 0; var wBptr = 0; for (var i = 0; i < 16; i++) { if (f.fcb[i] > 0) { rBptr = wBptr = 0; GetALB(ref buff, 0, bin_file, f.fcb[i], dirStart, allocBlock, sectorSize, spt, skewMap); for (var j = 0; j < cpmAlb; j++) { if (fcbNum > 0) { for (var l = 0; l < 128; l++) { wBuff[wBptr++] = buff[rBptr++]; } } fcbNum--; } bin_out.Write(wBuff, 0, wBptr); } } } bin_out.Close(); file_out.Close(); bin_file.Close(); file.Close(); return(result); }
//***************** Extract File CP/M IMD // Call ReadImdDisk to make sure image is in memory // Check to make sure file is in DirList public int ExtractFileCPMImd(Form1.DiskFileEntry diskFileEntry) { var diskImage = diskFileEntry.DiskImageName; //var fileNameListtemp = new List<CPMFile.DirList>(); long diskUsed = 0, diskTotal = 0; int result = 0; var fileNameListTemp = ReadImdDir(diskImage, ref diskTotal); var obj = fileNameList.FirstOrDefault(x => x.fname == diskFileEntry.FileName); if (obj != null) { var encoding = new UTF8Encoding(); var dir = string.Format("{0}_Files", diskImage); // create directory name and check if directory exists if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } fnameb = encoding.GetBytes(diskFileEntry.FileName); // Create output File var name = diskFileEntry.FileName.Substring(0, 8).Trim(' '); var ext = diskFileEntry.FileName.Substring(8, 3).Trim(' '); var file_name = string.Format("{0}\\{1}.{2}", dir, name, ext); if (File.Exists(file_name)) { if (MessageBox.Show("File exists, Overwrite it?", "File Exists", MessageBoxButtons.YesNo) == DialogResult.No) { result = 0; return(result); } else { file_name = file_name + "1"; } } var file_out = File.Create(file_name); var bin_out = new BinaryWriter(file_out); // Read file data from memory buffer byte[] wBuff = new byte[fileNameList[0].fsize * 1024 + 256]; // write buffer = file size plus a buffer int wBPtr = 0; var t0 = 0; foreach (var f in obj.fcbList) { t0++; var fcbNum = f.fcbnum; // number of 128 byte CP/M records in the FCB for (var i = 0; i < 16 / albNumSize && fcbNum > 0; i++) // read each fcb block in record. may be 8 or 16 values { if (f.fcb[i] > 0) // only process valid allocation blocks { var sectPerAlb = albSize / sectorSize; //var t2 = f.fcb[i] * sectPerAlb + dirSectStart; // debug for (var albCnt = 0; albCnt < sectPerAlb; albCnt++) // number of sectors to read in this allocation block { //var t3 = f.fcb[i] * sectPerAlb + dirSectStart + albCnt; var bufPtr = diskMap[f.fcb[i] * sectPerAlb + dirSectStart + albCnt]; // location of sector in buf[] var bufData = buf[bufPtr]; // get IMD sector marker. If odd, a sector worth of data follows if (bufData % 2 > 0) // IMD sector marker. odd number equals sector worth of data { bufPtr++; // point to first data byte int k = 0; // declared outside for loop to preserve value for (; k < sectorSize / 128 && k < fcbNum; k++) // read only one sector or the number of fcb records left { for (var j = 0; j < 128; j++) { wBuff[wBPtr++] = buf[bufPtr++]; } } fcbNum -= k; // decrement fcbnum counter by number of records read } else // IMD marker even, sector is compressed. next byte equals sector data { bufPtr++; int k = 0; for (; k < sectorSize / 128 && k < fcbNum; k++) { for (var j = 0; j < 128; j++) { wBuff[wBPtr++] = buf[bufPtr]; } } fcbNum -= k; // decrement fcbnum counter by number of records read } } } } } wBPtr--; bin_out.Write(wBuff, 0, wBPtr); bin_out.Close(); file_out.Close(); result = 1; } else { MessageBox.Show(diskFileEntry.FileName + " error. File not found in DirList", "Error", MessageBoxButtons.OK); } return(result); }