示例#1
0
bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
{
	int track_count = 0;
	int head_count = 0;
	int track_spt;
	int offset = 0;
	const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
	std::vector<uint8_t> imagebuf(max_size);
	uint8_t header[12];

	io_generic_read(io, header, 0, 12);
	head_count = header[9];

	if(header[0] == 't')
	{
		td0dsk_t disk_decode;

		disk_decode.floppy_file = io;
		disk_decode.init_Decode();
		disk_decode.floppy_file_offset = 12;
		disk_decode.Decode(&imagebuf[0], max_size);
	}
	else
		io_generic_read(io, &imagebuf[0], 12, io_generic_size(io));

	if(header[7] & 0x80)
		offset = 10 + imagebuf[2] + (imagebuf[3] << 8);

	track_spt = imagebuf[offset];
	if(track_spt == 255) // Empty file?
		return false;

	switch(header[6])
	{
		case 2:
			if((imagebuf[offset + 2] & 0x7f) == 2) // ?
			{
				if(head_count == 2)
					image->set_variant(floppy_image::DSHD);
				else
					return false; // single side hd?
				break;
			}
			/* no break; could be qd, won't know until tracks are counted */
		case 1:
			if(head_count == 2)
				image->set_variant(floppy_image::DSDD);
			else
				image->set_variant(floppy_image::SSDD);
			break;
		case 4:
			if((imagebuf[offset + 2] & 0x7f) == 2) // ?
			{
				if(head_count == 2)
					image->set_variant(floppy_image::DSHD);
				else
					return false; // single side 3.5?
				break;
			} else
				image->set_variant(floppy_image::SSDD);
			break;
			/* no break */
		case 3:
			if(head_count == 2)
			{
				if(form_factor == floppy_image::FF_525)
					image->set_variant(floppy_image::DSQD);
				else
					image->set_variant(floppy_image::DSDD);
			}
			else
			{
				if(form_factor == floppy_image::FF_525)
					image->set_variant(floppy_image::SSQD);
				else
					return false; // single side 3.5?
			}
			break;
	}

	static const int rates[3] = { 250000, 300000, 500000 };
	int rate = (header[5] & 0x7f) >= 3 ? 500000 : rates[header[5] & 0x7f];
	int rpm = form_factor == floppy_image::FF_8 || (form_factor == floppy_image::FF_525 && rate >= 300000) ? 360 : 300;
	int base_cell_count = rate*60/rpm;

	while(track_spt != 255)
	{
		desc_pc_sector sects[256];
		uint8_t sect_data[65536];
		int sdatapos = 0;
		int track = imagebuf[offset + 1];
		int head = imagebuf[offset + 2] & 1;
		bool fm = (header[5] & 0x80) || (imagebuf[offset + 2] & 0x80); // ?
		offset += 4;
		for(int i = 0; i < track_spt; i++)
		{
			uint8_t *hs = &imagebuf[offset];
			uint16_t size;
			offset += 6;

			sects[i].track       = hs[0];
			sects[i].head        = hs[1];
			sects[i].sector      = hs[2];
			sects[i].size        = hs[3];
			sects[i].deleted     = (hs[4] & 4) == 4;
			sects[i].bad_crc     = (hs[4] & 2) == 2;

			if(hs[4] & 0x30)
				size = 0;
			else
			{
				offset += 3;
				size = 128 << hs[3];
				int j, k;
				switch(hs[8])
				{
					default:
						return false;
					case 0:
						memcpy(&sect_data[sdatapos], &imagebuf[offset], size);
						offset += size;
						break;
					case 1:
						offset += 4;
						k = (hs[9] + (hs[10] << 8)) * 2;
						k = (k <= size) ? k : size;
						for(j = 0; j < k; j += 2)
						{
							sect_data[sdatapos + j] = hs[11];
							sect_data[sdatapos + j + 1] = hs[12];
						}
						if(k < size)
							memset(&sect_data[sdatapos + k], '\0', size - k);
						break;
					case 2:
						k = 0;
						while(k < size)
						{
							uint16_t len = imagebuf[offset];
							uint16_t rep = imagebuf[offset + 1];
							offset += 2;
							if(!len)
							{
								memcpy(&sect_data[sdatapos + k], &imagebuf[offset], rep);
								offset += rep;
								k += rep;
							}
							else
							{
								len = (1 << len);
								rep = len * rep;
								rep = ((rep + k) <= size) ? rep : (size - k);
								for(j = 0; j < rep; j += len)
									memcpy(&sect_data[sdatapos + j + k], &imagebuf[offset], len);
								k += rep;
								offset += len;
							}
						}
						break;
				}
			}

			sects[i].actual_size = size;

			if(size)
			{
				sects[i].data = &sect_data[sdatapos];
				sdatapos += size;
			}
			else
				sects[i].data = nullptr;
		}
		track_count = track;

		if(fm)
			build_pc_track_fm(track, head, image, base_cell_count, track_spt, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
		else
			build_pc_track_mfm(track, head, image, base_cell_count*2, track_spt, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));

		track_spt = imagebuf[offset];
	}
	if((track_count > 50) && (form_factor == floppy_image::FF_525)) // ?
	{
		if(image->get_variant() == floppy_image::DSDD)
			image->set_variant(floppy_image::DSQD);
		else if(image->get_variant() == floppy_image::SSDD)
			image->set_variant(floppy_image::SSQD);
	}
	return true;
}
示例#2
0
bool cqm_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
	dynamic_buffer imagebuf(max_size);
	UINT8 header[CQM_HEADER_SIZE];
	io_generic_read(io, header, 0, CQM_HEADER_SIZE);

	int sector_size      = (header[0x04] << 8) | header[0x03];
	int sector_per_track = (header[0x11] << 8) | header[0x10];
	int heads            = (header[0x13] << 8) | header[0x12];
	int tracks           = header[0x5b];
//  int blind            = header[0x58];    // 0=DOS, 1=blind, 2=HFS
	int density          = header[0x59];    // 0=DD, 1=HD, 2=ED
	int comment_size     = (header[0x70] << 8) | header[0x6f];
	int sector_base      = header[0x71] + 1;
//  int interleave       = header[0x74];    // TODO
//  int skew             = header[0x75];    // TODO
//  int drive            = header[0x76];    // source drive type: 1=5.25" 360KB, 2=5.25" 1.2MB, 3=3.5" 720KB, 4=3.5" 1.44MB, 6=3.5" 2.88MB, 8" is unknown (0 or 5?)

	switch(density)
	{
		case 0:
			if (form_factor == floppy_image::FF_525 && tracks > 50)
				image->set_variant(heads == 1 ? floppy_image::SSQD : floppy_image::DSQD);
			else
				image->set_variant(heads == 1 ? floppy_image::SSDD : floppy_image::DSDD);
			break;
		case 1:
			if (heads == 1)
				return false; // single side HD ?
			image->set_variant(floppy_image::DSHD);
			break;
		case 2:
			if (heads == 1)
				return false; // single side ED ?
			image->set_variant(floppy_image::DSED);
		default:
			return false;
	}

	static const int rates[3] = { 250000, 300000, 500000 };
	int rate = density >= 3 ? 500000 : rates[density];
	int rpm = form_factor == floppy_image::FF_8 || (form_factor == floppy_image::FF_525 && rate >= 300000) ? 360 : 300;
	int base_cell_count = rate*60/rpm;

	int cqm_size = io_generic_size(io);
	dynamic_buffer cqmbuf(cqm_size);
	io_generic_read(io, &cqmbuf[0], 0, cqm_size);

	// decode the RLE data
	for (int s = 0, pos = CQM_HEADER_SIZE + comment_size; pos < cqm_size; )
	{
		INT16 len = (cqmbuf[pos + 1] << 8) | cqmbuf[pos];
		pos += 2;
		if(len < 0)
		{
			len = -len;
			memset(&imagebuf[s], cqmbuf[pos], len);
			pos++;
		}
		else
		{
			memcpy(&imagebuf[s], &cqmbuf[pos], len);
			pos += len;
		}

		s += len;
	}

	int ssize;
	for(ssize=0; (128 << ssize) < sector_size; ssize++)
		;

	desc_pc_sector sects[256];
	for(int track = 0, pos = 0; track < tracks; track++)
		for(int head = 0; head < heads; head++)
		{
			for(int sector = 0; sector < sector_per_track; sector++)
			{
				sects[sector].track       = track;
				sects[sector].head        = head;
				sects[sector].sector      = sector_base + sector;
				sects[sector].size        = ssize;
				sects[sector].deleted     = false;
				sects[sector].bad_crc     = false;
				sects[sector].actual_size = sector_size;
				sects[sector].data        = &imagebuf[pos];
				pos += sector_size;
			}

			build_pc_track_mfm(track, head, image, base_cell_count*2, sector_per_track, sects, calc_default_pc_gap3_size(form_factor, sector_size));
		}

	return true;
}