1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /*********************************************************************
4 
5     formats/ccvf_dsk.c
6 
7     Compucolor Virtual Floppy Disk Image format
8 
9 *********************************************************************/
10 
11 #include "formats/ccvf_dsk.h"
12 
13 #include "coretmpl.h" // BIT
14 
15 
ccvf_format()16 ccvf_format::ccvf_format()
17 {
18 	formats = file_formats;
19 }
20 
ccvf_format(const format * _formats)21 ccvf_format::ccvf_format(const format *_formats)
22 {
23 	formats = _formats;
24 }
25 
name() const26 const char *ccvf_format::name() const
27 {
28 	return "ccvf";
29 }
30 
description() const31 const char *ccvf_format::description() const
32 {
33 	return "Compucolor Virtual Floppy Disk Image";
34 }
35 
extensions() const36 const char *ccvf_format::extensions() const
37 {
38 	return "ccvf";
39 }
40 
41 const ccvf_format::format ccvf_format::file_formats[] = {
42 	{
43 		floppy_image::FF_525, floppy_image::SSSD,
44 		(int) ((1./(9600*8))*1000000000), 10, 41, 1, 128, {}, 0, { 0,5,1,6,2,7,3,8,4,9 }
45 	},
46 	{}
47 };
48 
identify(io_generic * io,uint32_t form_factor)49 int ccvf_format::identify(io_generic *io, uint32_t form_factor)
50 {
51 	char h[36];
52 
53 	io_generic_read(io, h, 0, 36);
54 	if(!memcmp(h, "Compucolor Virtual Floppy Disk Image", 36))
55 		return 100;
56 
57 	return 0;
58 }
59 
get_desc_8n1(const format & f,int & current_size)60 floppy_image_format_t::desc_e* ccvf_format::get_desc_8n1(const format &f, int &current_size)
61 {
62 	static floppy_image_format_t::desc_e desc[] = {
63 		/* 00 */ { SECTOR_LOOP_START, 0, -1 },
64 		/* 01 */ {   RAWBITS, 0xffff, 3 },
65 		/* 02 */ {   RAWBYTE, 0xff, 3 },
66 		/* 03 */ {   CRC_FCS_START, 1 },
67 		/* 04 */ {     _8N1, 0x55, 1 },
68 		/* 05 */ {     TRACK_ID_8N1 },
69 		/* 06 */ {     SECTOR_ID_8N1 },
70 		/* 07 */ {   CRC_END, 1 },
71 		/* 08 */ {   CRC, 1 },
72 		/* 09 */ {   _8N1, 0xff, 3 },
73 		/* 10 */ {   CRC_FCS_START, 2 },
74 		/* 11 */ {     _8N1, 0x5a, 1 },
75 		/* 12 */ {     SECTOR_DATA_8N1, -1 },
76 		/* 13 */ {   CRC_END, 2 },
77 		/* 14 */ {   CRC, 2 },
78 		/* 15 */ { SECTOR_LOOP_END },
79 		/* 16 */ { RAWBYTE, 0xff, 0 },
80 		/* 17 */ { RAWBITS, 0xffff, 0 },
81 		/* 18 */ { END }
82 	};
83 
84 	current_size = 120 + (1+1+1+2)*10 + 3*10 + (1+f.sector_base_size+2)*10;
85 
86 	current_size *= f.sector_count;
87 	return desc;
88 }
89 
load(io_generic * io,uint32_t form_factor,floppy_image * image)90 bool ccvf_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
91 {
92 	const format &f = formats[0];
93 
94 	uint64_t size = io_generic_size(io);
95 	std::vector<uint8_t> img(size);
96 	io_generic_read(io, &img[0], 0, size);
97 
98 	std::string ccvf = std::string((const char *)&img[0], size);
99 	std::vector<uint8_t> bytes(78720);
100 
101 	int start = 0, end = 0;
102 	std::string line;
103 	uint32_t byteoffs = 0;
104 	char hex[3] = {0};
105 
106 	do {
107 		end = ccvf.find_first_of(10, start);
108 		line.assign(ccvf.substr(start, end));
109 		if (line.find("Compucolor Virtual Floppy Disk Image") != std::string::npos && line.find("Label") != std::string::npos && line.find("Track") != std::string::npos) {
110 			for (int byte = 0; byte < 32; byte++) {
111 				if (byteoffs==78720) break;
112 				hex[0]=line[byte * 2];
113 				hex[1]=line[(byte * 2) + 1];
114 				bytes[byteoffs++] = strtol(hex, nullptr, 16);
115 			}
116 		}
117 		start = end + 1;
118 	} while (start > 0 && end != -1);
119 
120 	uint64_t pos = 0;
121 	int total_size = 200000000/f.cell_size;
122 
123 	for(int track=0; track < f.track_count; track++) {
124 		std::vector<uint32_t> buffer;
125 		int offset = 0;
126 
127 		for (int i=0; i<1920 && pos<size; i++, pos++) {
128 			for (int bit=0; bit<8; bit++) {
129 				bit_w(buffer, util::BIT(bytes[pos], bit), f.cell_size);
130 			}
131 		}
132 
133 		if (offset < total_size) {
134 			// pad the remainder of the track with sync
135 			int count = total_size-buffer.size();
136 			for (int i=0; i<count;i++) {
137 				bit_w(buffer, (track > 0) ? 1 : 0, f.cell_size);
138 			}
139 		}
140 
141 		generate_track_from_levels(track, 0, buffer, 0, image);
142 	}
143 
144 	image->set_variant(f.variant);
145 
146 	return true;
147 }
148 
supports_save() const149 bool ccvf_format::supports_save() const
150 {
151 	return false;
152 }
153 
154 const floppy_format_type FLOPPY_CCVF_FORMAT = &floppy_image_format_creator<ccvf_format>;
155