mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	First draft of the DiskCopy 4.2 image writer.
This commit is contained in:
		
							
								
								
									
										13
									
								
								lib/bytes.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								lib/bytes.h
									
									
									
									
									
								
							| @@ -1,6 +1,8 @@ | ||||
| #ifndef BYTES_H | ||||
| #define BYTES_H | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| class ByteReader; | ||||
| class ByteWriter; | ||||
|  | ||||
| @@ -10,6 +12,7 @@ public: | ||||
|     Bytes(); | ||||
|     Bytes(unsigned size); | ||||
|     Bytes(const uint8_t* ptr, size_t len); | ||||
|     Bytes(const std::string& data); | ||||
|     Bytes(std::initializer_list<uint8_t> data); | ||||
|     Bytes(std::shared_ptr<std::vector<uint8_t>> data); | ||||
|     Bytes(std::shared_ptr<std::vector<uint8_t>> data, unsigned start, unsigned end); | ||||
| @@ -271,6 +274,16 @@ public: | ||||
|  | ||||
|     ByteWriter& operator += (std::istream& stream); | ||||
|  | ||||
| 	ByteWriter& append(const char* data) | ||||
| 	{ | ||||
| 		return *this += Bytes((const uint8_t*)data, strlen(data)); | ||||
| 	} | ||||
|  | ||||
| 	ByteWriter& append(const std::string& data) | ||||
| 	{ | ||||
| 		return *this += Bytes(data); | ||||
| 	} | ||||
|  | ||||
|     ByteWriter& append(const Bytes data) | ||||
|     { | ||||
|         return *this += data; | ||||
|   | ||||
							
								
								
									
										169
									
								
								lib/imagewriter/diskcopyimagewriter.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								lib/imagewriter/diskcopyimagewriter.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| #include "globals.h" | ||||
| #include "flags.h" | ||||
| #include "dataspec.h" | ||||
| #include "sector.h" | ||||
| #include "sectorset.h" | ||||
| #include "imagewriter/imagewriter.h" | ||||
| #include "fmt/format.h" | ||||
| #include "ldbs.h" | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
|  | ||||
| static const char LABEL[] = "FluxEngine image"; | ||||
|  | ||||
| static void write_and_update_checksum(ByteWriter& bw, uint32_t& checksum, const Bytes& data) | ||||
| { | ||||
| 	ByteReader br(data); | ||||
| 	while (!br.eof()) | ||||
| 	{ | ||||
| 		uint32_t i = br.read_be16(); | ||||
| 		checksum += i; | ||||
| 		checksum = (checksum >> 1) | (checksum << 31); | ||||
| 		bw.write_be16(i); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class DiskCopyImageWriter : public ImageWriter | ||||
| { | ||||
| public: | ||||
| 	DiskCopyImageWriter(const SectorSet& sectors, const ImageSpec& spec): | ||||
| 		ImageWriter(sectors, spec) | ||||
| 	{} | ||||
|  | ||||
| 	void writeImage() | ||||
| 	{ | ||||
| 		bool mfm = false; | ||||
|  | ||||
| 		if (spec.bytes == 524) | ||||
| 		{ | ||||
| 			/* GCR disk */ | ||||
| 		} | ||||
| 		else if (spec.bytes == 512) | ||||
| 		{ | ||||
| 			/* MFM disk */ | ||||
| 			mfm = true; | ||||
| 		} | ||||
| 		else | ||||
| 			Error() << "this image is not compatible with the DiskCopy 4.2 format"; | ||||
|  | ||||
|  | ||||
| 		std::cout << "writing DiskCopy 4.2 image\n" | ||||
| 		          << fmt::format("{} tracks, {} heads, {} sectors, {} bytes per sector; {}\n", | ||||
| 				  		spec.cylinders, spec.heads, spec.sectors, spec.bytes, | ||||
| 						mfm ? "MFM" : "GCR"); | ||||
|  | ||||
| 		auto sectors_per_track = [&](int track) -> int | ||||
| 		{ | ||||
| 			if (mfm) | ||||
| 				return spec.sectors; | ||||
|  | ||||
| 			if (track < 16) | ||||
| 				return 12; | ||||
| 			if (track < 32) | ||||
| 				return 11; | ||||
| 			if (track < 48) | ||||
| 				return 10; | ||||
| 			if (track < 64) | ||||
| 				return 9; | ||||
| 			return 8; | ||||
| 		}; | ||||
|  | ||||
| 		Bytes image; | ||||
| 		ByteWriter bw(image); | ||||
|  | ||||
| 		/* Write the actual sectr data. */ | ||||
|  | ||||
| 		uint32_t dataChecksum = 0; | ||||
| 		uint32_t tagChecksum = 0; | ||||
| 		uint32_t offset = 0x54; | ||||
| 		uint32_t sectorDataStart = offset; | ||||
| 		for (int track = 0; track < spec.cylinders; track++) | ||||
| 		{ | ||||
| 			for (int head = 0; head < spec.heads; head++) | ||||
| 			{ | ||||
| 				int sectorCount = sectors_per_track(track); | ||||
| 				for (int sectorId = 0; sectorId < sectorCount; sectorId++) | ||||
| 				{ | ||||
| 					const auto& sector = sectors.get(track, head, sectorId); | ||||
| 					if (sector) | ||||
| 					{ | ||||
| 						bw.seek(offset); | ||||
| 						write_and_update_checksum(bw, dataChecksum, sector->data.slice(0, 512)); | ||||
| 					} | ||||
| 					offset += 512; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		uint32_t sectorDataEnd = offset; | ||||
| 		if (!mfm) | ||||
| 		{ | ||||
| 			for (int track = 0; track < spec.cylinders; track++) | ||||
| 			{ | ||||
| 				for (int head = 0; head < spec.heads; head++) | ||||
| 				{ | ||||
| 					int sectorCount = sectors_per_track(track); | ||||
| 					for (int sectorId = 0; sectorId < sectorCount; sectorId++) | ||||
| 					{ | ||||
| 						const auto& sector = sectors.get(track, head, sectorId); | ||||
| 						if (sector) | ||||
| 						{ | ||||
| 							bw.seek(offset); | ||||
| 							write_and_update_checksum(bw, tagChecksum, sector->data.slice(512, 12)); | ||||
| 						} | ||||
| 						offset += 12; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		uint32_t tagDataEnd = offset; | ||||
|  | ||||
| 		/* Write the header. */ | ||||
|  | ||||
| 		uint8_t encoding; | ||||
| 		uint8_t format; | ||||
| 		if (mfm) | ||||
| 		{ | ||||
| 			format = 0x22; | ||||
| 			if (spec.sectors == 18) | ||||
| 				encoding = 3; | ||||
| 			else | ||||
| 				encoding = 2; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (spec.heads == 2) | ||||
| 			{ | ||||
| 				encoding = 1; | ||||
| 				format = 0x22; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				encoding = 0; | ||||
| 				format = 0x02; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		bw.seek(0); | ||||
| 		bw.write_8(sizeof(LABEL)); | ||||
| 		bw.append(LABEL); | ||||
| 		bw.seek(0x40); | ||||
| 		bw.write_be32(sectorDataEnd - sectorDataStart); /* data size */ | ||||
| 		bw.write_be32(tagDataEnd - sectorDataEnd); /* tag size */ | ||||
| 		bw.write_be32(dataChecksum); /* data checksum */ | ||||
| 		bw.write_be32(tagChecksum); /* tag checksum */ | ||||
| 		bw.write_8(encoding); /* encoding */ | ||||
| 		bw.write_8(format); /* format byte */ | ||||
| 		bw.write_be16(0x0100); /* magic number */ | ||||
|  | ||||
| 		image.writeToFile(spec.filename); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<ImageWriter> ImageWriter::createDiskCopyImageWriter( | ||||
| 	const SectorSet& sectors, const ImageSpec& spec) | ||||
| { | ||||
|     return std::unique_ptr<ImageWriter>(new DiskCopyImageWriter(sectors, spec)); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -13,6 +13,7 @@ std::map<std::string, ImageWriter::Constructor> ImageWriter::formats = | ||||
| 	{".adf", ImageWriter::createImgImageWriter}, | ||||
| 	{".d64", ImageWriter::createD64ImageWriter}, | ||||
| 	{".d81", ImageWriter::createImgImageWriter}, | ||||
| 	{".diskcopy", ImageWriter::createDiskCopyImageWriter}, | ||||
| 	{".img", ImageWriter::createImgImageWriter}, | ||||
| 	{".ldbs", ImageWriter::createLDBSImageWriter}, | ||||
| }; | ||||
|   | ||||
| @@ -29,6 +29,8 @@ private: | ||||
| 		const SectorSet& sectors, const ImageSpec& spec); | ||||
|     static std::unique_ptr<ImageWriter> createD64ImageWriter( | ||||
| 		const SectorSet& sectors, const ImageSpec& spec); | ||||
|     static std::unique_ptr<ImageWriter> createDiskCopyImageWriter( | ||||
| 		const SectorSet& sectors, const ImageSpec& spec); | ||||
|  | ||||
| 	static Constructor findConstructor(const ImageSpec& spec); | ||||
|  | ||||
|   | ||||
| @@ -154,6 +154,7 @@ buildlibrary libbackend.a \ | ||||
| 	lib/imagereader/imagereader.cc \ | ||||
| 	lib/imagereader/imgimagereader.cc \ | ||||
| 	lib/imagewriter/d64imagewriter.cc \ | ||||
| 	lib/imagewriter/diskcopyimagewriter.cc \ | ||||
| 	lib/imagewriter/imagewriter.cc \ | ||||
| 	lib/imagewriter/imgimagewriter.cc \ | ||||
| 	lib/imagewriter/ldbsimagewriter.cc \ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user