Exemple #1
0
bool dip_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	int heads, tracks, spt, bps;

	//For the moment we only support this disk structure...
	//2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
	heads = 2;
	tracks = 77;
	spt = 8;
	bps = 1024;

	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];

	for (int track = 0; track < tracks; track++)
		for (int head = 0; head < heads; head++)
		{
			io_generic_read(io, sect_data, 0x100 + 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));
		}

	return true;
}
bool pc98fdi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT8 h[32];

	io_generic_read(io, h, 0, 32);

	UINT32 hsize         = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x8));
	UINT32 sector_size   = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x10));
	UINT32 sector_count  = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x14));
	UINT32 head_count    = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x18));
	UINT32 track_count   = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x1c));

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

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

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

	for(int track=0; track < track_count; track++)
		for(int head=0; head < head_count; head++) {
			io_generic_read(io, sect_data, hsize + sector_size*sector_count*(track*head_count + head), sector_size*sector_count);

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

			build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sector_size));
		}

	return true;
}
Exemple #3
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;
}
Exemple #4
0
bool d88_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
{
	uint8_t h[32];

	io_generic_read(io, h, 0, 32);

	int cell_count = 0;
	int track_count = 0;
	int head_count = 0;
	switch(h[0x1b]) {
	case 0x00:
		cell_count = 100000;
		track_count = 42;
		head_count = 2;
		image->set_variant(floppy_image::DSDD);
		break;

	case 0x10:
		cell_count = 100000;
		track_count = 82;
		head_count = 2;
		image->set_variant(floppy_image::DSQD);
		break;

	case 0x20:
		cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
		track_count = 82;
		head_count = 2;
		image->set_variant(floppy_image::DSHD);
		break;

	case 0x30:
		cell_count = 100000;
		track_count = 42;
		head_count = 1;
		image->set_variant(floppy_image::SSDD);
		break;

	case 0x40:
		cell_count = 100000;
		track_count = 82;
		head_count = 1;
		image->set_variant(floppy_image::SSQD);
		break;
	}

	if(!head_count)
		return false;

	uint32_t track_pos[164];
	io_generic_read(io, track_pos, 32, 164*4);

	for(int track=0; track < track_count; track++)
		for(int head=0; head < head_count; head++) {
			int pos = little_endianize_int32(track_pos[track * head_count + head]);
			if(!pos)
				continue;

			desc_pc_sector sects[256];
			uint8_t sect_data[65536];
			int sdatapos = 0;
			int sector_count = 1;
			for(int i=0; i<sector_count; i++) {
				uint8_t hs[16];
				io_generic_read(io, hs, pos, 16);
				pos += 16;

				uint16_t size = little_endianize_int16(*(uint16_t *)(hs+14));
				if(i == 0) {
					sector_count = little_endianize_int16(*(uint16_t *)(hs+4));
					// Support broken vfman converter
					if(sector_count == 0x1000)
						sector_count = 0x10;
				}

				sects[i].track       = hs[0];
				sects[i].head        = hs[1];
				sects[i].sector      = hs[2];
				sects[i].size        = hs[3];
				sects[i].actual_size = size;
				sects[i].deleted     = hs[7] != 0;
				sects[i].bad_crc     = false;

				if(size) {
					sects[i].data    = sect_data + sdatapos;
					io_generic_read(io, sects[i].data, pos, size);
					pos += size;
					sdatapos += size;

				} else
					sects[i].data    = nullptr;
			}

			build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
		}

	return true;
}
Exemple #5
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;
}
Exemple #6
0
bool d88_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT8 h[32];

	io_generic_read(io, h, 0, 32);

	int cell_count = 0;
	int track_count = 0;
	int head_count = 0;
	switch(h[0x1b]) {
	case 0x00:
		cell_count = 100000;
		track_count = 42;
		head_count = 2;
		image->set_variant(floppy_image::DSDD);
		break;

	case 0x10:
		cell_count = 100000;
		track_count = 82;
		head_count = 2;
		image->set_variant(floppy_image::DSQD);
		break;

	case 0x20:
		cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
		track_count = 82;
		head_count = 2;
		image->set_variant(floppy_image::DSHD);
		break;

	case 0x30:
		cell_count = 100000;
		track_count = 42;
		head_count = 1;
		image->set_variant(floppy_image::SSDD);
		break;

	case 0x40:
		cell_count = 100000;
		track_count = 82;
		head_count = 1;
		image->set_variant(floppy_image::SSQD);
		break;
	}

	if(!head_count)
		return false;

	UINT32 track_pos[164];
	io_generic_read(io, track_pos, 32, 164*4);

	for(int track=0; track < track_count; track++)
		for(int head=0; head < head_count; head++) {
			int pos = LITTLE_ENDIANIZE_INT32(track_pos[track * head_count + head]);
			if(!pos)
				continue;

			desc_pc_sector sects[256];
			UINT8 sect_data[65536];
			int sdatapos = 0;
			int sector_count = 1;
			for(int i=0; i<sector_count; i++) {
				UINT8 hs[16];
				io_generic_read(io, hs, pos, 16);
				pos += 16;

				UINT16 size = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+14));
				if(i == 0)
					sector_count = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+4));

				sects[i].track       = hs[0];
				sects[i].head        = hs[1];
				sects[i].sector      = hs[2];
				sects[i].size        = hs[3];
				sects[i].actual_size = size;
				sects[i].deleted     = hs[7] != 0;
				sects[i].bad_crc     = false;

				if(size) {
					sects[i].data    = sect_data + sdatapos;
					io_generic_read(io, sects[i].data, pos, size);
					pos += size;
					sdatapos += size;

				} else
					sects[i].data    = NULL;
			}

			build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
		}

	return true;
}
Exemple #7
0
bool fdd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT8 hsec[0x0c];

	// sector map
	UINT8 num_secs[160];
	UINT8 tracks[160 * 26];
	UINT8 heads[160 * 26];
	UINT8 secs[160 * 26];
	UINT8 fill_vals[160 * 26];
	UINT32 sec_offs[160 * 26];
	UINT8 sec_sizes[160 * 26];

	int pos = 0xdc;

	for (int track = 0; track < 160; track++)
	{
		int curr_num_sec = 0, curr_track_size = 0;
		for (int sect = 0; sect < 26; sect++)
		{
			// read sector map for this sector
			io_generic_read(io, hsec, pos, 0x0c);
			pos += 0x0c;

			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];
			fill_vals[(track * 26) + sect] = hsec[4];
			sec_offs[(track * 26) + sect] = little_endianize_int32(*(UINT32 *)(hsec + 0x08));

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

	int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
	desc_pc_sector sects[256];
	UINT8 sect_data[65536];
	int cur_sec_map = 0, sector_size;

	for (int track = 0; track < 160; track++)
	{
		int cur_pos = 0;
		for (int i = 0; i < num_secs[track]; i++)
		{
			cur_sec_map = track * 26 + i;
			sector_size = 128 << sec_sizes[cur_sec_map];

			if (sec_offs[cur_sec_map] == 0xffffffff)
				memset(sect_data + cur_pos, fill_vals[cur_sec_map], sector_size);
			else
				io_generic_read(io, sect_data + cur_pos, sec_offs[cur_sec_map], sector_size);

			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 + cur_pos;
			cur_pos += sector_size;
		}

		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])));
	}

	return true;
}
Exemple #8
0
bool dsk_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT8 header[0x100];
	bool extendformat = FALSE;

	UINT64 image_size = io_generic_size(io);

	io_generic_read(io, &header, 0, sizeof(header));
	if ( memcmp( header, EXT_FORMAT_HEADER, 16 ) ==0) {
		extendformat = TRUE;
	}

	int heads = header[0x31];
	int skip = 1;
	if (heads==1) {
		skip = 2;
	}
	int tracks  = header[0x30];
	UINT64 track_offsets[84*2];
	int cnt =0;
	if (!extendformat) {
		int tmp = 0x100;
		for (int i=0; i<tracks * heads; i++)
		{
			track_offsets[cnt] = tmp;
			tmp += pick_integer_le(header, 0x32, 2);
			cnt += skip;
		}
	} else  {
		int tmp = 0x100;
		for (int i=0; i<tracks * heads; i++)
		{
			int length = header[0x34 + i] << 8;
			if (length != 0)
			{
				track_offsets[cnt] = tmp;
				tmp += length;
			}
			else
			{
				track_offsets[cnt] = image_size;
			}

			cnt += skip;
		}
	}

	int counter = 0;
	for(int track=0; track < tracks; track++) {
		for(int side=0; side < heads; side++) {
			if(track_offsets[(track<<1)+side] >= image_size)
				continue;
			track_header tr;
			io_generic_read(io, &tr,track_offsets[(track<<1)+side],sizeof(tr));
			desc_pc_sector sects[256];
			UINT8 sect_data[65536];
			int sdatapos = 0;
			int pos = track_offsets[(track<<1)+side] + 0x100;
			for(int j=0;j<tr.number_of_sector;j++) {
				sector_header sector;
				io_generic_read(io, &sector,track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j),sizeof(sector));

				sects[j].track       = sector.track;
				sects[j].head        = sector.side;
				sects[j].sector      = sector.sector_id;
				sects[j].size        = sector.sector_size_code;
				if(extendformat)
					sects[j].actual_size = sector.data_length;
				else
					sects[j].actual_size = 128 << tr.sector_size_code;
				sects[j].deleted     = sector.fdc_status_reg1 == 0xb2;
				sects[j].bad_crc     = sector.fdc_status_reg1 == 0xb5;

				if(!sects[j].deleted) {
					sects[j].data = sect_data + sdatapos;
					io_generic_read(io, sects[j].data, pos, sects[j].actual_size);
					sdatapos += sects[j].actual_size;

				} else
					sects[j].data = NULL;

				if(extendformat)
					pos += sector.data_length;
				else
					pos += 128 << tr.sector_size_code;
			}
			build_pc_track_mfm(track, side, image, 100000, tr.number_of_sector, sects, tr.gap3_length);
			counter++;
		}
	}
	return true;
}
Exemple #9
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;
}
Exemple #10
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;
}
Exemple #11
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;
}