summaryrefslogblamecommitdiffstatshomepage
path: root/src/lib/formats/sdf_dsk.cpp
blob: b2cd4a4e7ab319d7eb1c8cc9e4de218335a813e4 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                                      
 







































                                                                            
 















                                                                                         
 




































                                                                                
 

                                                                                                                                         
 
                                                         
 
                                                                           
 






                                                                                                                                            
 











































































                                                                                                                
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol, tim lindner
/*********************************************************************

    formats/sdf_dsk.h

    SDF disk images. Format created by Darren Atkinson for use with
    his CoCoSDC floppy disk emulator.

    http://cocosdc.blogspot.com/p/sd-card-socket-sd-card-socket-is-push.html

*********************************************************************/

#include "sdf_dsk.h"
#include <assert.h>

sdf_format::sdf_format()
{
}


const char *sdf_format::name() const
{
	return "sdf";
}


const char *sdf_format::description() const
{
	return "SDF disk image";
}


const char *sdf_format::extensions() const
{
	return "sdf";
}


int sdf_format::identify(io_generic *io, uint32_t form_factor)
{
	uint8_t header[HEADER_SIZE];

	uint64_t size = io_generic_size(io);

	if (size < HEADER_SIZE)
	{
		return 0;
	}

	io_generic_read(io, header, 0, HEADER_SIZE);

	int tracks = header[4];
	int heads = header[5];

	// Check magic bytes
	if (header[0] != 'S' || header[1] != 'D' || header[2] != 'F' || header[3] != '1')
	{
		return 0;
	}

	// Check heads
	if (heads != 1 && heads != 2)
	{
		return 0;
	}

	if (size == HEADER_SIZE + heads * tracks * TOTAL_TRACK_SIZE)
	{
		return 100;
	}

	return 0;
}


bool sdf_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
{
	uint8_t header[HEADER_SIZE];
	std::vector<uint8_t> track_data(TOTAL_TRACK_SIZE);
	std::vector<uint32_t> raw_track_data;

	io_generic_read(io, header, 0, HEADER_SIZE);

	const int tracks = header[4];
	const int heads = header[5];

	if (heads == 2)
	{
		image->set_variant(floppy_image::DSDD);
	}
	else
	{
		image->set_variant(floppy_image::SSDD);
	}

	for (int track = 0; track < tracks; track++)
	{
		for (int head = 0; head < heads; head++)
		{
			int iam_location = -1;
			int idam_location[SECTOR_SLOT_COUNT+1];
			int dam_location[SECTOR_SLOT_COUNT+1];
			raw_track_data.clear();

			// Read track
			io_generic_read(io, &track_data[0], HEADER_SIZE + ( heads * track + head ) * TOTAL_TRACK_SIZE, TOTAL_TRACK_SIZE);

			int sector_count = track_data[0];

			if (sector_count > SECTOR_SLOT_COUNT) return false;

			// Transfer IDAM and DAM locations to table
			for (int i = 0; i < SECTOR_SLOT_COUNT+1; i++)
			{
				if (i < sector_count )
				{
					idam_location[i] = ((track_data[ 8 * (i+1) + 1] << 8 | track_data[ 8 * (i+1)]) & 0x3FFF) - 4;
					dam_location[i] = ((track_data[ 8 * (i+1) + 1 + 2] << 8 | track_data[ 8 * (i+1) + 2]) & 0x3FFF) - 4;

					if (idam_location[i] > TOTAL_TRACK_SIZE) return false;
					if (dam_location[i] > TOTAL_TRACK_SIZE) return false;
				}
				else
				{
					idam_location[i] = -1;
					dam_location[i] = -1;
				}
			}

			// Find IAM location
			for (int i = idam_location[0] - 1; i >= TRACK_HEADER_SIZE + 3; i--)
			{
				// It's usually 3 bytes but several dumped tracks seem to contain only 2 bytes
				if (track_data[i] == 0xfc && track_data[i-1] == 0xc2 && track_data[i-2] == 0xc2)
				{
					iam_location = i - 3;
					break;
				}
			}

			int idam_index = 0;
			int dam_index = 0;
			for (int offset = TRACK_HEADER_SIZE; offset < TRACK_HEADER_SIZE + TRACK_SIZE; offset++)
			{
				if (offset == iam_location)
				{
					// Write IAM
					raw_w(raw_track_data, 16, 0x5224);
					raw_w(raw_track_data, 16, 0x5224);
					raw_w(raw_track_data, 16, 0x5224);
					offset += 3;
				}

				if (offset == idam_location[idam_index])
				{
					raw_w(raw_track_data, 16, 0x4489);
					raw_w(raw_track_data, 16, 0x4489);
					raw_w(raw_track_data, 16, 0x4489);
					idam_index += 1;
					offset += 3;
				}

				if (offset == dam_location[dam_index])
				{
					raw_w(raw_track_data, 16, 0x4489);
					raw_w(raw_track_data, 16, 0x4489);
					raw_w(raw_track_data, 16, 0x4489);
					dam_index += 1;
					offset += 3;
				}

				mfm_w(raw_track_data, 8, track_data[offset]);
			}

			generate_track_from_levels(track, head, raw_track_data, 0, image);
		}
	}

	return true;
}


bool sdf_format::save(io_generic *io, floppy_image *image)
{
	return false;
}


bool sdf_format::supports_save() const
{
	return false;
}


const floppy_format_type FLOPPY_SDF_FORMAT = &floppy_image_format_creator<sdf_format>;