mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Merge pull request #522 from tdaede/fix_fluxop_space_rpm
Add D88 image writer.
This commit is contained in:
		| @@ -274,14 +274,19 @@ FluxEngine also supports a number of file system image formats. When using the | ||||
|   - `<filename.d88>` | ||||
|  | ||||
|   Read from a [D88 image file](https://www.pc98.org/project/doc/d88.html), | ||||
|   commonly used by various Japanese PC emulators, including the NEC PC-88. **Read only.** | ||||
|   commonly used by various Japanese PC emulators, including the NEC PC-88. | ||||
|    | ||||
|   FluxEngine is currently limited to reading only the first floppy image in a | ||||
|   D88 file. | ||||
|   D88 file. When writing, a single unnamed floppy will be created | ||||
|   within the image file. | ||||
|    | ||||
|   The D88 reader should be used with the `ibm` profile and will override | ||||
|   most encoding parameters on a track-by-track basis. | ||||
|    | ||||
|   The D88 writer should likewise be used with the `ibm` profile in most | ||||
|   circumstances as it can represent arbitrary sector layouts as read | ||||
|   from the floppy. | ||||
|    | ||||
|   - `<filename.nfd>` | ||||
|  | ||||
|   Read from a [NFD r0 image file](https://www.pc98.org/project/doc/nfdr0.html), | ||||
|   | ||||
							
								
								
									
										113
									
								
								lib/imagewriter/d88imagewriter.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								lib/imagewriter/d88imagewriter.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,113 @@ | ||||
| #include "globals.h" | ||||
| #include "flags.h" | ||||
| #include "sector.h" | ||||
| #include "imagewriter/imagewriter.h" | ||||
| #include "image.h" | ||||
| #include "lib/config.pb.h" | ||||
| #include "imginputoutpututils.h" | ||||
| #include "fmt/format.h" | ||||
| #include "logger.h" | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
|  | ||||
| class D88ImageWriter : public ImageWriter | ||||
| { | ||||
| public: | ||||
| 	D88ImageWriter(const ImageWriterProto& config): | ||||
| 		ImageWriter(config) | ||||
| 	{} | ||||
|  | ||||
| 	void writeImage(const Image& image) | ||||
| 	{ | ||||
| 		const Geometry geometry = image.getGeometry(); | ||||
|  | ||||
| 		int tracks = geometry.numTracks; | ||||
| 		int sides = geometry.numSides; | ||||
|  | ||||
| 		std::ofstream outputFile(_config.filename(), std::ios::out | std::ios::binary); | ||||
| 		if (!outputFile.is_open()) | ||||
| 			Error() << "cannot open output file"; | ||||
|  | ||||
| 		Bytes header; | ||||
| 		ByteWriter headerWriter(header); | ||||
| 		for(int i = 0; i < 26; i++) { | ||||
| 			headerWriter.write_8(0x0); // image name + reserved bytes | ||||
| 		} | ||||
| 		headerWriter.write_8(0x00); // not write protected | ||||
| 		if (geometry.numTracks > 42) { | ||||
| 			headerWriter.write_8(0x20); // 2HD | ||||
| 		} else { | ||||
| 			headerWriter.write_8(0x00); // 2D | ||||
| 		} | ||||
| 		headerWriter.write_le32(0); // disk size (will be overridden at the end of writing) | ||||
| 		for (int i = 0; i < 164; i++) { | ||||
| 			headerWriter.write_le32(0); // track pointer (will be overridden in track loop) | ||||
| 		} | ||||
| 		header.writeTo(outputFile); | ||||
|  | ||||
| 		uint32_t trackOffset = 688; | ||||
|  | ||||
| 		for (int track = 0; track < geometry.numTracks * geometry.numSides; track++) | ||||
| 		{ | ||||
| 			headerWriter.seek(0x20 + 4 * track); | ||||
| 			headerWriter.write_le32(trackOffset); | ||||
| 			int side = track & 1; | ||||
| 			std::vector<std::shared_ptr<const Sector>> sectors; | ||||
| 			for (int sectorId = 0; sectorId < geometry.numSectors; sectorId++) | ||||
| 			{ | ||||
| 				const auto& sector = image.get(track >> 1, side, sectorId); | ||||
| 				if (sector) | ||||
| 				{ | ||||
| 					sectors.push_back(sector); | ||||
| 				} | ||||
| 			} | ||||
| 			std::sort(begin(sectors), | ||||
| 					  end(sectors), | ||||
| 					  [](std::shared_ptr<const Sector> a, std::shared_ptr<const Sector> b) { return a->position < b->position; }); | ||||
| 			for (auto& sector : sectors) | ||||
| 			{ | ||||
| 				Bytes sectorBytes; | ||||
| 				ByteWriter sectorWriter(sectorBytes); | ||||
| 				sectorWriter.write_8(sector->logicalTrack); | ||||
| 				sectorWriter.write_8(sector->logicalSide); | ||||
| 				sectorWriter.write_8(sector->logicalSector); | ||||
| 				sectorWriter.write_8(24 - std::countl_zero(uint32_t(sector->data.size()))); | ||||
| 				sectorWriter.write_le16(sectors.size()); | ||||
| 				sectorWriter.write_8(0x00); // always write mfm | ||||
| 				sectorWriter.write_8(0x00); // always write not deleted data | ||||
| 				if (sector->status == Sector::Status::BAD_CHECKSUM) { | ||||
| 					sectorWriter.write_8(0xB0); | ||||
| 				} else { | ||||
| 					sectorWriter.write_8(0x00); | ||||
| 				} | ||||
| 				sectorWriter.write_8(0x00); // reserved | ||||
| 				sectorWriter.write_8(0x00); | ||||
| 				sectorWriter.write_8(0x00); | ||||
| 				sectorWriter.write_8(0x00); | ||||
| 				sectorWriter.write_8(0x00); | ||||
| 				sectorWriter.write_le16(sector->data.size()); | ||||
| 				sectorBytes.writeTo(outputFile); | ||||
| 				sector->data.writeTo(outputFile); | ||||
| 				trackOffset += sectorBytes.size(); | ||||
| 				trackOffset += sector->data.size(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		headerWriter.seek(0x1c); | ||||
| 		headerWriter.write_le32(outputFile.tellp()); | ||||
| 		outputFile.seekp(0); | ||||
| 		header.writeTo(outputFile); | ||||
|  | ||||
| 		Logger() << fmt::format("D88: wrote {} tracks, {} sides, {} kB total", | ||||
| 						tracks, sides, | ||||
| 						outputFile.tellp() / 1024); | ||||
| 	} | ||||
|  | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<ImageWriter> ImageWriter::createD88ImageWriter( | ||||
| 	const ImageWriterProto& config) | ||||
| { | ||||
|     return std::unique_ptr<ImageWriter>(new D88ImageWriter(config)); | ||||
| } | ||||
| @@ -32,6 +32,9 @@ std::unique_ptr<ImageWriter> ImageWriter::create(const ImageWriterProto& config) | ||||
| 		case ImageWriterProto::kRaw: | ||||
| 			return ImageWriter::createRawImageWriter(config); | ||||
|  | ||||
| 		case ImageWriterProto::kD88: | ||||
| 			return ImageWriter::createD88ImageWriter(config); | ||||
|  | ||||
| 		default: | ||||
| 			Error() << "bad output image config"; | ||||
| 			return std::unique_ptr<ImageWriter>(); | ||||
| @@ -45,6 +48,7 @@ void ImageWriter::updateConfigForFilename(ImageWriterProto* proto, const std::st | ||||
| 		{".adf",      [](auto* proto) { proto->mutable_img(); }}, | ||||
| 		{".d64",      [](auto* proto) { proto->mutable_d64(); }}, | ||||
| 		{".d81",      [](auto* proto) { proto->mutable_img(); }}, | ||||
| 		{".d88",      [](auto* proto) { proto->mutable_d88(); }}, | ||||
| 		{".diskcopy", [](auto* proto) { proto->mutable_diskcopy(); }}, | ||||
| 		{".dsk",      [](auto* proto) { proto->mutable_img(); }}, | ||||
| 		{".img",      [](auto* proto) { proto->mutable_img(); }}, | ||||
|   | ||||
| @@ -20,6 +20,7 @@ public: | ||||
|     static std::unique_ptr<ImageWriter> createLDBSImageWriter(const ImageWriterProto& config); | ||||
|     static std::unique_ptr<ImageWriter> createNsiImageWriter(const ImageWriterProto& config); | ||||
|     static std::unique_ptr<ImageWriter> createRawImageWriter(const ImageWriterProto& config); | ||||
|     static std::unique_ptr<ImageWriter> createD88ImageWriter(const ImageWriterProto& config); | ||||
|  | ||||
| public: | ||||
| 	void printMap(const Image& sectors); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ message LDBSOutputProto { | ||||
| message DiskCopyOutputProto {} | ||||
| message NsiOutputProto {} | ||||
| message RawOutputProto {} | ||||
| message D88OutputProto {} | ||||
|  | ||||
| message ImageWriterProto { | ||||
| 	optional string filename = 1 [(help) = "filename of output sector image"]; | ||||
| @@ -40,6 +41,7 @@ message ImageWriterProto { | ||||
| 		DiskCopyOutputProto diskcopy = 5; | ||||
| 		NsiOutputProto nsi = 6; | ||||
| 		RawOutputProto raw = 7; | ||||
| 		D88OutputProto d88 = 8; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -466,6 +466,7 @@ buildlibrary libbackend.a \ | ||||
|     lib/imagereader/fdiimagereader.cc \ | ||||
|     lib/imagereader/d88imagereader.cc \ | ||||
|     lib/imagewriter/d64imagewriter.cc \ | ||||
|     lib/imagewriter/d88imagewriter.cc \ | ||||
|     lib/imagewriter/diskcopyimagewriter.cc \ | ||||
|     lib/imagewriter/imagewriter.cc \ | ||||
|     lib/imagewriter/imgimagewriter.cc \ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user