mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	support for validating ImageSpecs before we actually want to read/write an image, so as to allow us to check the extension *before* wasting time reading a disk. Make .d81 an alias of .img.
		
			
				
	
	
		
			129 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "globals.h"
 | |
| #include "image.h"
 | |
| #include "flags.h"
 | |
| #include "dataspec.h"
 | |
| #include "sector.h"
 | |
| #include "sectorset.h"
 | |
| #include "imagewriter/imagewriter.h"
 | |
| #include "fmt/format.h"
 | |
| 
 | |
| std::map<std::string, ImageWriter::Constructor> ImageWriter::formats =
 | |
| {
 | |
| 	{".adf", ImageWriter::createImgImageWriter},
 | |
| 	{".d64", ImageWriter::createD64ImageWriter},
 | |
| 	{".d81", ImageWriter::createImgImageWriter},
 | |
| 	{".img", ImageWriter::createImgImageWriter},
 | |
| 	{".ldbs", ImageWriter::createLDBSImageWriter},
 | |
| };
 | |
| 
 | |
| static bool ends_with(const std::string& value, const std::string& ending)
 | |
| {
 | |
|     if (ending.size() > value.size())
 | |
|         return false;
 | |
|     return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
 | |
| }
 | |
| 
 | |
| ImageWriter::Constructor ImageWriter::findConstructor(const ImageSpec& spec)
 | |
| {
 | |
|     const auto& filename = spec.filename;
 | |
| 
 | |
| 	for (const auto& e : formats)
 | |
| 	{
 | |
| 		if (ends_with(filename, e.first))
 | |
| 			return e.second;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec)
 | |
| {
 | |
| 	verifyImageSpec(spec);
 | |
| 	return findConstructor(spec)(sectors, spec);
 | |
| }
 | |
| 
 | |
| void ImageWriter::verifyImageSpec(const ImageSpec& spec)
 | |
| {
 | |
| 	if (!findConstructor(spec))
 | |
| 		Error() << "unrecognised image filename extension";
 | |
| }
 | |
| 
 | |
| ImageWriter::ImageWriter(const SectorSet& sectors, const ImageSpec& spec):
 | |
|     sectors(sectors),
 | |
|     spec(spec)
 | |
| {}
 | |
| 
 | |
| void ImageWriter::adjustGeometry()
 | |
| {
 | |
| 	if (!spec.initialised)
 | |
| 	{
 | |
| 		sectors.calculateSize(spec.cylinders, spec.heads, spec.sectors, spec.bytes);
 | |
|         spec.initialised = true;
 | |
| 		std::cout << "Autodetecting output geometry\n";
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ImageWriter::printMap()
 | |
| {
 | |
| 	int badSectors = 0;
 | |
| 	int missingSectors = 0;
 | |
| 	int totalSectors = 0;
 | |
| 	std::cout << "H.SS Tracks --->" << std::endl;
 | |
| 	for (int head = 0; head < spec.heads; head++)
 | |
| 	{
 | |
| 		for (int sectorId = 0; sectorId < spec.sectors; sectorId++)
 | |
| 		{
 | |
| 			std::cout << fmt::format("{}.{:2} ", head, sectorId);
 | |
| 			for (int track = 0; track < spec.cylinders; track++)
 | |
| 			{
 | |
| 				const auto& sector = sectors.get(track, head, sectorId);
 | |
| 				if (!sector)
 | |
| 				{
 | |
| 					std::cout << 'X';
 | |
| 					missingSectors++;
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					switch (sector->status)
 | |
| 					{
 | |
| 						case Sector::OK:
 | |
|                             std::cout << '.';
 | |
|                             break;
 | |
| 
 | |
|                         case Sector::BAD_CHECKSUM:
 | |
|                             std::cout << 'B';
 | |
|                             badSectors++;
 | |
|                             break;
 | |
| 
 | |
|                         case Sector::CONFLICT:
 | |
|                             std::cout << 'C';
 | |
|                             badSectors++;
 | |
|                             break;
 | |
| 
 | |
|                         default:
 | |
|                             std::cout << '?';
 | |
|                             break;
 | |
|                     }
 | |
| 				}
 | |
| 				totalSectors++;
 | |
| 			}
 | |
| 			std::cout << std::endl;
 | |
| 		}
 | |
| 	}
 | |
| 	int goodSectors = totalSectors - missingSectors - badSectors;
 | |
| 	if (totalSectors == 0)
 | |
| 		std::cout << "No sectors in output; skipping analysis" << std::endl;
 | |
| 	else
 | |
| 	{
 | |
| 		std::cout << "Good sectors: " << goodSectors << "/" << totalSectors
 | |
| 				  << " (" << (100*goodSectors/totalSectors) << "%)"
 | |
| 				  << std::endl;
 | |
| 		std::cout << "Missing sectors: " << missingSectors << "/" << totalSectors
 | |
| 				  << " (" << (100*missingSectors/totalSectors) << "%)"
 | |
| 				  << std::endl;
 | |
| 		std::cout << "Bad sectors: " << badSectors << "/" << totalSectors
 | |
| 				  << " (" << (100*badSectors/totalSectors) << "%)"
 | |
| 				  << std::endl;
 | |
|     }
 | |
| }
 |