Beispiel #1
0
bool imd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT64 size = io_generic_size(io);
	UINT8 *img = global_alloc_array(UINT8, size);
	io_generic_read(io, img, 0, size);

	UINT64 pos;
	for(pos=0; pos < size && img[pos] != 0x1a; pos++);
	pos++;

	if(pos >= size)
		return false;

	while(pos < size) {
		UINT8 mode = img[pos++];
		UINT8 track = img[pos++];
		UINT8 head = img[pos++];
		UINT8 sector_count = img[pos++];
		UINT8 ssize = img[pos++];

		if(ssize == 0xff)
			throw emu_fatalerror("imd_format: Unsupported variable sector size on track %d head %d", track, head);

		UINT32 actual_size = ssize < 7 ? 128 << ssize : 8192;

		static const int rates[3] = { 500000, 300000, 250000 };
		bool fm = mode < 3;
		int rate = rates[mode % 3];
		int rpm = form_factor == floppy_image::FF_8 || (form_factor == floppy_image::FF_525 && rate >= 300000) ? 360 : 300;
		int cell_count = (fm ? 1 : 2)*rate*60/rpm;

		const UINT8 *snum = img+pos;
		pos += sector_count;
		const UINT8 *tnum = head & 0x80 ? img+pos : NULL;
		if(tnum)
			pos += sector_count;
		const UINT8 *hnum = head & 0x40 ? img+pos : NULL;
		if(hnum)
			pos += sector_count;

		head &= 0x3f;

		int gap_3 = calc_default_pc_gap3_size(form_factor, actual_size);

		desc_pc_sector sects[256];

		for(int i=0; i<sector_count; i++) {
			UINT8 stype = img[pos++];
			sects[i].track       = tnum ? tnum[i] : track;
			sects[i].head        = hnum ? hnum[i] : head;
			sects[i].sector      = snum[i];
			sects[i].size        = ssize;
			sects[i].actual_size = actual_size;

			if(stype == 0 || stype > 8) {
				sects[i].data = NULL;

			} else {
				sects[i].deleted = stype == 3 || stype == 4 || stype == 7 || stype == 8;
				sects[i].bad_crc = stype == 5 || stype == 6 || stype == 7 || stype == 8;

				if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
					sects[i].data = global_alloc_array(UINT8, actual_size);
					memset(sects[i].data, img[pos++], actual_size);

				} else {
					sects[i].data = img + pos;
					pos += actual_size;
				}
			}
		}

		if(fm)
			build_pc_track_fm(track, head, image, cell_count, sector_count, sects, gap_3);
		else
			build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, gap_3);

		for(int i=0; i<sector_count; i++)
			if(sects[i].data && (sects[i].data < img || sects[i].data >= img+size))
				global_free(sects[i].data);
	}

	global_free(img);
	return true;
}
Beispiel #2
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;
}
Beispiel #3
0
bool dcp_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT8 h[0xa2];
	int heads, tracks, spt, bps;
	bool is_hdb = false;

	io_generic_read(io, h, 0, 0xa2);

	// First byte is the disk format:
	switch (h[0])
	{
		case 0x01:
		default:
			//01h: 2HD-8 sector (1.25MB) (BKDSK .HDM) (aka 2HS)
			//2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
			heads = 2;
			tracks = 77;
			spt = 8;
			bps = 1024;
			break;
		case 0x02:
			//02H: 2HD-15 sector (1.21MB) (BKDSK .HD5) (aka 2HC)
			//2 sides, 80 tracks, 15 sectors/track, 512 bytes/sector = 1228800 bytes (360rpm)
			heads = 2;
			tracks = 80;
			spt = 15;
			bps = 512;
			break;
		case 0x03:
			//03H: 2HQ-18 sector (1.44MB) (BKDSK .HD4) (aka 2HDE)
			//2 sides, 80 tracks, 18 sectors/track, 512 bytes/sector = 1474560 bytes (300rpm)
			heads = 2;
			tracks = 80;
			spt = 18;
			bps = 512;
			break;
		case 0x04:
			//04H: 2DD-8 sector (640KB) (BKDSK .DD6)
			//2 sides, 80 tracks, 8 sectors/track, 512 bytes/sector = 655360 bytes (300rpm)
			heads = 2;
			tracks = 80;
			spt = 8;
			bps = 512;
			break;
		case 0x05:
			//05h: 2DD-9 sector ( 720KB) (BKDSK .DD9)
			//2 sides, 80 tracks, 9 sectors/track, 512 bytes/sector = 737280 bytes (300rpm)
			heads = 2;
			tracks = 80;
			spt = 9;
			bps = 512;
			break;
		case 0x08:
			//08h: 2HD-9 sector (1.44MB)
			//2 sides, 80 tracks, 9 sectors/track, 1024 bytes/sector = 1474560 bytes (300rpm)(??)
			heads = 2;
			tracks = 80;
			spt = 9;
			bps = 1024;
			break;
		case 0x11:
			//11h: BASIC-2HD (BKDSK .HDB)
			//Head 0 Track 0 - FM encoding - 26 sectors of 128 bytes = 1 track
			//Head 1 Track 0 - MFM encoding - 26 sectors of 256 bytes = 1 track
			//Head 0 Track 1 to Head 1 Track 77 - 26 sectors of 256 bytes = 152 tracks
			//2 sides, 77 tracks, 26 sectors/track, 256 bytes/sector (except for head 0 track 0) = 1021696 bytes (360rpm)
			is_hdb = true;
			heads = 2;
			tracks = 77;
			spt = 26;
			bps = 256;
			break;
		case 0x19:
			//19h: BASIC 2DD (BKDSK .DDB)
			//2 sides, 80 tracks, 16 sectors/track, 256 bytes/sector = 655360 bytes (300rpm)
			heads = 2;
			tracks = 80;
			spt = 16;
			bps = 256;
			break;
		case 0x21:
			//21H: 2HD-26 sector
			//2 sides, 80 tracks, 26 sectors/track, 256 bytes/sector = 1064960 bytes (??rpm)(??)
			heads = 2;
			tracks = 80;
			spt = 26;
			bps = 256;
			break;
	}

	int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;

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

	desc_pc_sector sects[256];
	UINT8 sect_data[65536];

	if (!is_hdb)
	{
		for (int track = 0; track < tracks; track++)
			for (int head = 0; head < heads; head++)
			{
				io_generic_read(io, sect_data, 0xa2 + bps * spt * (track * heads + head), bps * spt);

				for (int i = 0; i < spt; i++)
				{
					sects[i].track       = track;
					sects[i].head        = head;
					sects[i].sector      = i + 1;
					sects[i].size        = ssize;
					sects[i].actual_size = bps;
					sects[i].deleted     = false;
					sects[i].bad_crc     = false;
					sects[i].data        = sect_data + i * bps;
				}

				build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
			}
	}
	else    // FIXME: the code below is untested, because no image was found... there might be some silly mistake in the disk geometry!
	{
		// Read Head 0 Track 0 is FM with 26 sectors of 128bytes instead of 256
		io_generic_read(io, sect_data, 0xa2, 128 * spt);

		for (int i = 0; i < spt; i++)
		{
			sects[i].track       = 0;
			sects[i].head        = 0;
			sects[i].sector      = i + 1;
			sects[i].size        = 0;
			sects[i].actual_size = 128;
			sects[i].deleted     = false;
			sects[i].bad_crc     = false;
			sects[i].data        = sect_data + i * 128;
		}

		build_pc_track_fm(0, 0, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, 128));

		// Read Head 1 Track 0 is MFM with 26 sectors of 256bytes
		io_generic_read(io, sect_data, 0xa2 + 128 * spt, bps * spt);

		for (int i = 0; i < spt; i++)
		{
			sects[i].track       = 0;
			sects[i].head        = 1;
			sects[i].sector      = i + 1;
			sects[i].size        = ssize;
			sects[i].actual_size = bps;
			sects[i].deleted     = false;
			sects[i].bad_crc     = false;
			sects[i].data        = sect_data + i * bps;
		}

		build_pc_track_mfm(0, 1, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));

		// Read other tracks as usual
		UINT32 data_offs = 0xa2 + (26 * 0x80) + (26 * 0x100);
		for (int track = 1; track < tracks; track++)
			for (int head = 0; head < heads; head++)
			{
				io_generic_read(io, sect_data, data_offs + bps * spt * ((track - 1) * heads + head), bps * spt);

				for (int i = 0; i < spt; i++)
				{
					sects[i].track       = track;
					sects[i].head        = head;
					sects[i].sector      = i + 1;
					sects[i].size        = ssize;
					sects[i].actual_size = bps;
					sects[i].deleted     = false;
					sects[i].bad_crc     = false;
					sects[i].data        = sect_data + i * bps;
				}

				build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
			}
	}

	return true;
}
Beispiel #4
0
bool nfd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
{
	uint64_t size = io_generic_size(io);
	uint8_t h[0x120], hsec[0x10];
	io_generic_read(io, h, 0, 0x120);
	int format_version = !strncmp((const char *)h, "T98FDDIMAGE.R0", 14) ? 0 : 1;

	// sector map (the 164th entry is only used by rev.1 format, loops with track < 163 are correct for rev.0)
	uint8_t disk_type = 0;
	uint8_t num_secs[164];
	uint8_t num_specials[164];
	uint32_t track_sizes[164];
	uint8_t tracks[164 * 26];
	uint8_t heads[164 * 26];
	uint8_t secs[164 * 26];
	uint8_t mfm[164 * 26];
	uint8_t sec_sizes[164 * 26];

	uint32_t hsize = little_endianize_int32(*(uint32_t *)(h+0x110));

	int pos = 0x120;

	// set up sector map
	if (format_version == 1)
	{
		for (int track = 0; track < 164; track++)
		{
			int curr_track_size = 0;
			// read sector map absolute location
			io_generic_read(io, hsec, pos, 4);
			pos += 4;
			uint32_t secmap_addr = little_endianize_int32(*(uint32_t *)(hsec));

			if (secmap_addr)
			{
				// read actual sector map for the sectors of this track
				// for rev.1 format the first 0x10 are a track summary:
				// first WORD is # of sectors, second WORD is # of special data sectors
				io_generic_read(io, hsec, secmap_addr, 0x10);
				secmap_addr += 0x10;
				num_secs[track] = little_endianize_int16(*(uint16_t *)(hsec));
				num_specials[track] = little_endianize_int16(*(uint16_t *)(hsec + 0x2));

				for (int sect = 0; sect < num_secs[track]; sect++)
				{
					io_generic_read(io, hsec, secmap_addr, 0x10);

					if (track == 0 && sect == 0)
						disk_type = hsec[0xb];  // can this change across the disk? I don't think so...
					secmap_addr += 0x10;

					tracks[(track * 26) + sect] = hsec[0];
					heads[(track * 26) + sect] = hsec[1];
					secs[(track * 26) + sect] = hsec[2];
					sec_sizes[(track * 26) + sect] = hsec[3];
					mfm[(track * 26) + sect] = hsec[4];

					curr_track_size += (128 << hsec[3]);
				}

				if (num_specials[track] > 0)
				{
					for (int sect = 0; sect < num_specials[track]; sect++)
					{
						io_generic_read(io, hsec, secmap_addr, 0x10);
						secmap_addr += 0x10;
						curr_track_size += (hsec[9] + 1) * little_endianize_int32(*(uint32_t *)(hsec + 0x0a));
					}
				}
			}
			else
			{
				num_secs[track] = 0;
				num_specials[track] = 0;
			}
			track_sizes[track] = curr_track_size;
		}
	}
	else
	{
		for (int track = 0; track < 163 && pos < hsize; track++)
		{
			int curr_num_sec = 0, curr_track_size = 0;
			for (int sect = 0; sect < 26; sect++)
			{
				// read sector map for this sector
				// for rev.0 format each sector uses 0x10 bytes
				io_generic_read(io, hsec, pos, 0x10);

				if (track == 0 && sect == 0)
					disk_type = hsec[0xa];  // can this change across the disk? I don't think so...
				pos += 0x10;

				if (hsec[0] == 0xff)    // unformatted/unused sector
					continue;

				tracks[(track * 26) + sect] = hsec[0];
				heads[(track * 26) + sect] = hsec[1];
				secs[(track * 26) + sect] = hsec[2];
				sec_sizes[(track * 26) + sect] = hsec[3];
				mfm[(track * 26) + sect] = hsec[4];

				curr_track_size += (128 << hsec[3]);
				curr_num_sec++;
			}

			num_secs[track] = curr_num_sec;
			track_sizes[track] = curr_track_size;
		}
	}

	// shouln't this be set-up depending on disk_type? gaplus does not like having less than 166666 cells
	int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;

	switch (disk_type)
	{
		case 0x10:  // 640K disk, 2DD
			image->set_variant(floppy_image::DSDD);
			break;
		//case 0x30:    // 1.44M disk, ?? (no images found)
		//  break;
		case 0x90:  // 1.2M disk, 2HD
		default:
			image->set_variant(floppy_image::DSHD);
			break;
	}

	desc_pc_sector sects[256];
	uint8_t sect_data[65536];
	int cur_sec_map = 0, sector_size;
	pos = hsize;

	for (int track = 0; track < 163 && pos < size; track++)
	{
		io_generic_read(io, sect_data, pos, track_sizes[track]);

		for (int i = 0; i < num_secs[track]; i++)
		{
			cur_sec_map = track * 26 + i;
			sector_size = 128 << sec_sizes[cur_sec_map];
			sects[i].track       = tracks[cur_sec_map];
			sects[i].head        = heads[cur_sec_map];
			sects[i].sector      = secs[cur_sec_map];
			sects[i].size        = sec_sizes[cur_sec_map];
			sects[i].actual_size = sector_size;
			sects[i].deleted     = false;
			sects[i].bad_crc     = false;
			sects[i].data        = sect_data + i * sector_size;
		}
		pos += track_sizes[track];

		// notice that the operation below might fail if sectors of the same track have variable sec_sizes,
		// because the gap3 calculation would account correctly only for the first sector...
		// examined images had constant sec_sizes in the each track, so probably this is not an issue
		if (mfm[track * 26])
			build_pc_track_mfm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
		else
			build_pc_track_fm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
	}

	return true;
}