2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 #include "../config.h"
14 static const uint16 crc_table[256] = {
15 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
16 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
17 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
18 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
19 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
20 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
21 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
22 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
23 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
24 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
25 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
26 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
27 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
28 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
29 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
30 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
33 // teledisk decoder table
34 static const uint8 d_code[256] = {
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
38 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
39 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
40 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
41 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
42 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
43 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
44 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
45 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
46 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
47 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
48 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
49 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
50 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
52 static const uint8 d_len[256] = {
53 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
54 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
55 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
56 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
57 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
58 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
59 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
60 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
61 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
62 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
63 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
64 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
65 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
66 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
67 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
68 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
70 static const int secsize[8] = {
71 128, 256, 512, 1024, 2048, 4096, 8192, 16384
74 static uint8 tmp_buffer[DISK_BUFFER_SIZE];
78 int ncyl, nside, nsec, size;
81 static const fd_format_t fd_formats[] = {
82 { MEDIA_TYPE_2D, 40, 1, 16, 256 }, // 1D 160KB
83 #if defined(SUPPORT_MEDIA_TYPE_1DD)
84 { MEDIA_TYPE_2DD, 80, 1, 16, 256 }, // 1DD 320KB
85 { MEDIA_TYPE_2DD, 80, 1, 9, 512 }, // 1DD 360KB
87 { MEDIA_TYPE_2D , 40, 2, 16, 256 }, // 2D 320KB
88 { MEDIA_TYPE_2D, 40, 2, 9, 512 }, // 2D 360KB
90 #if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200) || defined(_MZ2500)
91 { MEDIA_TYPE_2DD, 80, 2, 16, 256 }, // 2DD 640KB (MZ-2500)
93 { MEDIA_TYPE_2DD, 80, 2, 8, 512 }, // 2DD 640KB
95 { MEDIA_TYPE_2DD, 80, 2, 9, 512 }, // 2DD 720KB
96 #if defined(_PX7) || defined(_MSX1) || defined(_MSX2)
97 { MEDIA_TYPE_2DD, 81, 2, 9, 512 }, // 2DD 729KB
99 { MEDIA_TYPE_2HD, 80, 2, 15, 512 }, // 2HC 1.20MB
100 { MEDIA_TYPE_2HD, 77, 2, 8, 1024 }, // 2HD 1.25MB
101 { MEDIA_TYPE_144, 80, 2, 18, 512 }, // 2HD 1.44MB
102 { MEDIA_TYPE_144, 80, 2, 36, 512 }, // 2ED 2.88MB
106 #define IS_VALID_TRACK(offset) ((offset) >= 0x20 && (offset) < sizeof(buffer))
108 void DISK::open(_TCHAR path[], int bank)
110 // check current disk image
112 if(_tcsicmp(orig_path, path) == 0 && file_bank == bank) {
117 memset(buffer, 0, sizeof(buffer));
118 media_type = MEDIA_TYPE_UNK;
119 is_solid_image = is_fdi_image = false;
120 trim_required = false;
124 if(fi->Fopen(path, FILEIO_READ_BINARY)) {
125 bool converted = false;
127 _tcscpy_s(orig_path, _MAX_PATH, path);
128 _tcscpy_s(dest_path, _MAX_PATH, path);
129 _stprintf_s(temp_path, _MAX_PATH, _T("%s.$$$"), path);
132 write_protected = false; //FILEIO::IsFileProtected(path);
134 // is this d88 format ?
135 if(check_file_extension(path, _T(".d88")) || check_file_extension(path, _T(".d77"))) {
137 for(int i = 0; i < bank; i++) {
138 fi->Fseek(offset + 0x1c, SEEK_SET);
139 offset += fi->FgetUint32_LE();
141 fi->Fseek(offset + 0x1c, FILEIO_SEEK_SET);
142 file_size.d = fi->FgetUint32_LE();
143 fi->Fseek(offset, FILEIO_SEEK_SET);
144 fi->Fread(buffer, file_size.d, 1);
146 inserted = changed = true;
147 // trim_required = true;
149 // fix sector number from big endian to little endian
150 for(int trkside = 0; trkside < 164; trkside++) {
152 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
154 if(!IS_VALID_TRACK(offset.d)) {
157 uint8* t = buffer + offset.d;
158 pair sector_num, data_size;
159 sector_num.read_2bytes_le_from(t + 4);
160 bool is_be = (sector_num.b.l == 0 && sector_num.b.h >= 4);
162 sector_num.read_2bytes_be_from(t + 4);
163 sector_num.write_2bytes_le_to(t + 4);
165 for(int i = 0; i < sector_num.sd; i++) {
167 sector_num.write_2bytes_le_to(t + 4);
169 data_size.read_2bytes_le_from(t + 14);
170 t += data_size.sd + 0x10;
176 fi->Fseek(0, FILEIO_SEEK_END);
177 file_size.d = fi->Ftell();
178 fi->Fseek(0, FILEIO_SEEK_SET);
181 #if defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
182 // is this 2d format ?
183 if(check_file_extension(path, _T(".2d"))) {
184 if(solid_to_d88(MEDIA_TYPE_2D, 40, 2, 16, 256)) {
185 inserted = changed = is_solid_image = true;
188 fi->Fseek(0, FILEIO_SEEK_SET);
192 // check image file format
193 for(int i = 0;; i++) {
194 const fd_format_t *p = &fd_formats[i];
198 int len = p->ncyl * p->nside * p->nsec * p->size;
199 // 4096 bytes: FDI header ???
200 if(file_size.d == len || (file_size.d == (len + 4096) && (len == 655360 || len == 1261568))) {
201 if(file_size.d == len + 4096) {
203 fi->Fread(fdi_header, 4096, 1);
205 if(solid_to_d88(p->type, p->ncyl, p->nside, p->nsec, p->size)) {
206 inserted = changed = is_solid_image = true;
211 if(0 < file_size.d && file_size.d <= DISK_BUFFER_SIZE) {
212 memset(buffer, 0, sizeof(buffer));
213 fi->Fread(buffer, file_size.d, 1);
215 // check d88 format (temporary)
216 if(file_size.b.l == buffer[0x1c] && file_size.b.h == buffer[0x1d] && file_size.b.h2 == buffer[0x1e] && file_size.b.h3 == buffer[0x1f]) {
217 inserted = changed = true;
220 _stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), path);
224 if(memcmp(buffer, "TD", 2) == 0 || memcmp(buffer, "td", 2) == 0) {
225 // teledisk image file
226 inserted = changed = converted = teledisk_to_d88();
227 } else if(memcmp(buffer, "IMD", 3) == 0) {
228 // imagedisk image file
229 inserted = changed = converted = imagedisk_to_d88();
230 } else if(memcmp(buffer, "MV - CPC", 8) == 0) {
231 // standard cpdread image file
232 inserted = changed = converted = cpdread_to_d88(0);
233 } else if(memcmp(buffer, "EXTENDED", 8) == 0) {
234 // extended cpdread image file
235 inserted = changed = converted = cpdread_to_d88(1);
238 // failed to convert the disk image
246 FILEIO::RemoveFile(temp_path);
249 if(buffer[0x1a] != 0) {
251 write_protected = true;
256 FILEIO* fio = new FILEIO();
257 if(fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
258 fio->Fwrite(buffer, file_size.d, 1);
264 crc32 = getcrc32(buffer, file_size.d);
266 if(media_type == MEDIA_TYPE_UNK) {
267 if((media_type = buffer[0x1b]) == MEDIA_TYPE_2HD) {
268 for(int trkside = 0; trkside < 164; trkside++) {
270 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
272 if(!IS_VALID_TRACK(offset.d)) {
276 uint8 *t = buffer + offset.d;
277 pair sector_num, data_size;
278 sector_num.read_2bytes_le_from(t + 4);
279 data_size.read_2bytes_le_from(t + 14);
281 if(sector_num.sd >= 18 && data_size.sd == 512) {
282 media_type = MEDIA_TYPE_144;
289 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
290 // FIXME: ugly patch for FM-7 Gambler Jiko Chuushin Ha
291 if(media_type == MEDIA_TYPE_2D) {
293 pair offset, sector_num, data_size;
294 offset.read_4bytes_le_from(buffer + 0x20);
295 if(IS_VALID_TRACK(offset.d)) {
296 // check the sector (c,h,r,n)=(0,0,7,1)
297 uint8* t = buffer + offset.d;
298 sector_num.read_2bytes_le_from(t + 4);
299 for(int i = 0; i < sector_num.sd; i++) {
300 data_size.read_2bytes_le_from(t + 14);
301 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 7 && t[3] == 1) {
302 static const uint8 gambler[] = {0xb7, 0xde, 0xad, 0xdc, 0xdd, 0xcc, 0xde, 0xd7, 0xb1, 0x20, 0xbc, 0xde, 0xba, 0xc1, 0xad, 0xb3, 0xbc, 0xdd, 0xca};
303 if(memcmp((void *)(t + 0x30), gambler, sizeof(gambler)) == 0) {
304 is_special_disk = SPECIAL_DISK_FM7_GAMBLER;
308 t += data_size.sd + 0x10;
312 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
313 // FIXME: ugly patch for X1turbo ALPHA and X1 Batten Tanuki
314 if(media_type == MEDIA_TYPE_2D) {
317 offset.read_4bytes_le_from(buffer + 0x20);
318 if(IS_VALID_TRACK(offset.d)) {
319 // check first sector
320 static const uint8 batten[] = {0xca, 0xde, 0xaf, 0xc3, 0xdd, 0x20, 0xc0, 0xc7, 0xb7};
321 uint8 *t = buffer + offset.d;
322 #if defined(_X1TURBO) || defined(_X1TURBOZ)
323 if(strncmp((char *)(t + 0x11), "turbo ALPHA", 11) == 0) {
324 is_special_disk = SPECIAL_DISK_X1TURBO_ALPHA;
327 if(memcmp((void *)(t + 0x11), batten, sizeof(batten)) == 0) {
328 is_special_disk = SPECIAL_DISK_X1_BATTEN;
343 trim_required = false;
345 buffer[0x1a] = write_protected ? 0x10 : 0; // mey be changed
347 if(/*!write_protected &&*/ file_size.d && getcrc32(buffer, file_size.d) != crc32) {
349 FILEIO* fio = new FILEIO();
350 int pre_size = 0, post_size = 0;
351 uint8 *pre_buffer = NULL, *post_buffer = NULL;
353 // is this d88 format ?
354 if(check_file_extension(dest_path, _T(".d88")) || check_file_extension(dest_path, _T(".d77"))) {
355 if(fio->Fopen(dest_path, FILEIO_READ_BINARY)) {
356 fio->Fseek(0, FILEIO_SEEK_END);
357 uint32 total_size = fio->Ftell(), offset = 0;
358 for(int i = 0; i < file_bank; i++) {
359 fio->Fseek(offset + 0x1c, SEEK_SET);
360 offset += fio->FgetUint32_LE();
362 if((pre_size = offset) > 0) {
363 pre_buffer = (uint8 *)malloc(pre_size);
364 fio->Fseek(0, FILEIO_SEEK_SET);
365 fio->Fread(pre_buffer, pre_size, 1);
367 fio->Fseek(offset + 0x1c, SEEK_SET);
368 offset += fio->FgetUint32_LE();
369 if((post_size = total_size - offset) > 0) {
370 post_buffer = (uint8 *)malloc(post_size);
371 fio->Fseek(offset, FILEIO_SEEK_SET);
372 fio->Fread(post_buffer, post_size, 1);
377 if((FILEIO::IsFileExists(dest_path) && FILEIO::IsFileProtected(dest_path)) || !fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
378 _TCHAR tmp_path[_MAX_PATH];
379 _stprintf_s(tmp_path, _MAX_PATH, _T("temporary_saved_floppy_disk_#%d.d88"), drive_num);
380 fio->Fopen(emu->bios_path(tmp_path), FILEIO_WRITE_BINARY);
382 if(fio->IsOpened()) {
384 fio->Fwrite(pre_buffer, pre_size, 1);
388 fio->Fwrite(fdi_header, 4096, 1);
390 for(int trkside = 0; trkside < 164; trkside++) {
392 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
394 if(!IS_VALID_TRACK(offset.d)) {
397 uint8* t = buffer + offset.d;
398 pair sector_num, data_size;
399 sector_num.read_2bytes_le_from(t + 4);
401 for(int i = 0; i < sector_num.sd; i++) {
402 data_size.read_2bytes_le_from(t + 14);
403 fio->Fwrite(t + 0x10, data_size.sd, 1);
404 t += data_size.sd + 0x10;
408 fio->Fwrite(buffer, file_size.d, 1);
411 fio->Fwrite(post_buffer, post_size, 1);
425 inserted = write_protected = false;
427 sector_size.sd = sector_num.sd = 0;
431 bool DISK::get_track(int trk, int side)
433 sector_size.sd = sector_num.sd = 0;
434 invalid_format = false;
437 // disk not inserted or invalid media type
438 if(!(inserted && check_media_type())) {
443 int trkside = trk * 2 + (side & 1);
444 if(!(0 <= trkside && trkside < 164)) {
451 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
453 if(!IS_VALID_TRACK(offset.d)) {
458 sector = buffer + offset.d;
459 sector_num.read_2bytes_le_from(sector + 4);
461 data_size.read_2bytes_le_from(sector + 14);
463 // create each sector position in track
464 int sync_size = drive_mfm ? 12 : 6;
465 int am_size = drive_mfm ? 3 : 0;
466 int gap0_size = drive_mfm ? 80 : 40;
467 int gap1_size = drive_mfm ? 50 : 26;
468 int gap2_size = drive_mfm ? 22 : 11;
469 int gap3_size = 0, gap4_size;
471 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
473 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
474 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
475 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
477 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
478 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
479 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
483 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
484 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
485 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
487 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
488 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
489 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
494 int total = sync_size + (am_size + 1);
496 for(int i = 0; i < sector_num.sd; i++) {
497 data_size.read_2bytes_le_from(t + 14);
498 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
499 if(data_size.sd > 0) {
500 total += sync_size + (am_size + 1);
501 total += data_size.sd + 2;
506 t += data_size.sd + 0x10;
509 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (sector_num.sd + 1);
511 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
513 if(gap3_size < 8 || gap4_size < 8) {
514 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + sector_num.sd + 1);
515 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
517 if(gap3_size < 8 || gap4_size < 8) {
518 gap0_size = gap1_size = gap3_size = gap4_size = 32;
519 invalid_format = true;
521 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
524 total = preamble_size;
525 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
527 for(int i = 0; i < sector_num.sd; i++) {
528 data_size.read_2bytes_le_from(t + 14);
530 total = preamble_size + (get_track_size() - preamble_size - gap4_size) * i / sector_num.sd;
532 sync_position[i] = total;
533 total += sync_size + (am_size + 1);
534 id_position[i] = total;
535 total += (4 + 2) + gap2_size;
536 if(data_size.sd > 0) {
537 total += sync_size + (am_size + 1);
538 data_position[i] = total;
539 total += data_size.sd + 2;
541 data_position[i] = total; // FIXME
544 t += data_size.sd + 0x10;
549 bool DISK::make_track(int trk, int side)
551 int track_size = get_track_size();
553 if(!get_track(trk, side)) {
554 // create a dummy track
555 for(int i = 0; i < track_size; i++) {
562 int sync_size = drive_mfm ? 12 : 6;
563 int am_size = drive_mfm ? 3 : 0;
564 int gap2_size = drive_mfm ? 22 : 11;
565 uint8 gap_data = drive_mfm ? 0x4e : 0xff;
568 memset(track, gap_data, track_size);
569 int q = sync_position[array_length(sync_position) - 1];
572 for(int i = 0; i < sync_size; i++) {
576 for(int i = 0; i < am_size; i++) {
584 for(int i = 0; i < sector_num.sd; i++) {
586 data_size.read_2bytes_le_from(t + 14);
587 int p = sync_position[i];
590 for(int j = 0; j < sync_size; j++) {
591 if(p < track_size) track[p++] = 0x00;
594 for(int j = 0; j < am_size; j++) {
595 if(p < track_size) track[p++] = 0xa1;
597 if(p < track_size) track[p++] = 0xfe;
599 if(p < track_size) track[p++] = t[0];
600 if(p < track_size) track[p++] = t[1];
601 if(p < track_size) track[p++] = t[2];
602 if(p < track_size) track[p++] = t[3];
604 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
605 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
606 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
607 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
608 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
609 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
611 for(int j = 0; j < gap2_size; j++) {
612 if(p < track_size) track[p++] = gap_data;
615 if(data_size.sd > 0) {
617 for(int j = 0; j < sync_size; j++) {
618 if(p < track_size) track[p++] = 0x00;
621 for(int j = 0; j < am_size; j++) {
622 if(p < track_size) track[p++] = 0xa1;
624 if(p < track_size) track[p++] = (t[7] != 0) ? 0xf8 : 0xfb;
627 for(int j = 0; j < data_size.sd; j++) {
628 if(p < track_size) track[p++] = t[0x10 + j];
629 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0x10 + j]]);
631 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
632 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
634 t += data_size.sd + 0x10;
639 bool DISK::get_sector(int trk, int side, int index)
641 sector_size.sd = sector_num.sd = 0;
644 // disk not inserted or invalid media type
645 if(!(inserted && check_media_type())) {
650 if(trk == -1 && side == -1) {
654 int trkside = trk * 2 + (side & 1);
655 if(!(0 <= trkside && trkside < 164)) {
659 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
661 if(!IS_VALID_TRACK(offset.d)) {
666 uint8* t = buffer + offset.d;
667 sector_num.read_2bytes_le_from(t + 4);
669 if(index >= sector_num.sd) {
674 for(int i = 0; i < index; i++) {
676 data_size.read_2bytes_le_from(t + 14);
677 t += data_size.sd + 0x10;
683 void DISK::set_sector_info(uint8 *t)
691 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
692 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
693 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
694 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
695 id[4] = (crc >> 8) & 0xff;
696 id[5] = (crc >> 0) & 0xff;
697 // http://www,gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
698 // t[6]: 0x00 = double-density, 0x40 = single-density
699 // t[7]: 0x00 = normal, 0x10 = deleted mark
700 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
702 deleted = (t[7] != 0);
704 // if(ignore_crc()) {
705 // crc_error = false;
707 // crc_error = (((t[8] & 0xf0) != 0x00) && ((t[8] & 0xf0) != 0x10));
708 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
709 data_crc_error = ((t[8] & 0xf0) == 0xb0);
712 sector_size.read_2bytes_le_from(t + 14);
715 void DISK::set_deleted(bool value)
718 uint8 *t = sector - 0x10;
719 t[7] = value ? 0x10 : 0;
720 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
721 t[8] = (t[8] & 0x0f) | t[7];
727 void DISK::clear_data_crc_error()
730 uint8 *t = sector - 0x10;
731 t[8] = (t[8] & 0x0f) | t[7];
733 data_crc_error = false;
736 void DISK::set_data_mark_missing()
739 uint8 *t = sector - 0x10;
740 //t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]); // FIXME: always data crc error ?
741 t[8] = (t[8] & 0x0f) | 0xf0;
745 //addr_crc_error = value;
746 data_crc_error = false;
749 bool DISK::format_track(int trk, int side)
751 // disk not inserted or invalid media type
752 if(!(inserted && check_media_type())) {
757 int trkside = trk * 2 + (side & 1);
758 if(!(0 <= trkside && trkside < 164)) {
762 // create new empty track
765 trim_required = false;
767 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
769 offset.d = DISK_BUFFER_SIZE;
770 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
772 trim_required = true;
777 void DISK::insert_sector(uint8 c, uint8 h, uint8 r, uint8 n, bool deleted, bool data_crc_error, uint8 fill_data, int length)
779 uint8* t = buffer + DISK_BUFFER_SIZE;
782 for(int i = 0; i < (sector_num.sd - 1); i++) {
783 t[4] = sector_num.b.l;
784 t[5] = sector_num.b.h;
786 data_size.read_2bytes_le_from(t + 14);
787 t += data_size.sd + 0x10;
793 t[4] = sector_num.b.l;
794 t[5] = sector_num.b.h;
795 t[6] = drive_mfm ? 0 : 0x40;
796 t[7] = deleted ? 0x10 : 0;
797 t[8] = data_crc_error ? 0xb0 : t[7];
798 t[14] = (length >> 0) & 0xff;
799 t[15] = (length >> 8) & 0xff;
800 memset(t + 16, fill_data, length);
805 void DISK::sync_buffer()
809 trim_required = false;
813 void DISK::trim_buffer()
815 int max_tracks = 164;
816 uint32 dest_offset = 0x2b0;
819 memset(tmp_buffer, 0, sizeof(tmp_buffer));
820 memcpy(tmp_buffer, buffer, 0x20);
823 for(int trkside = 0; trkside < 164; trkside++) {
825 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
826 if(src_trk_offset.d != 0) {
828 if(src_trk_offset.d < 0x2b0) {
829 max_tracks = (src_trk_offset.d - 0x20) >> 2;
832 if(src_trk_offset.d != 0x2b0) {
833 max_tracks = (src_trk_offset.d - 0x20) >> 2;
834 if(max_tracks > 164) {
835 dest_offset = 0x20 + max_tracks * 4);
844 for(int trkside = 0; trkside < max_tracks; trkside++) {
846 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
848 pair dest_trk_offset;
849 dest_trk_offset.d = 0;
851 if(IS_VALID_TRACK(src_trk_offset.d)) {
852 uint8* t = buffer + src_trk_offset.d;
853 pair sector_num, data_size;
854 sector_num.read_2bytes_le_from(t + 4);
855 if(sector_num.sd != 0) {
856 dest_trk_offset.d = dest_offset;
857 for(int i = 0; i < sector_num.sd; i++) {
858 data_size.read_2bytes_le_from(t + 14);
859 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
860 dest_offset += data_size.sd + 0x10;
861 t += data_size.sd + 0x10;
865 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
869 file_size.d = dest_offset;
870 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
872 memset(buffer, 0, sizeof(buffer));
873 memcpy(buffer, tmp_buffer, (file_size.d > sizeof(buffer)) ? sizeof(buffer) : file_size.d);
880 } else if(inserted) {
881 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
883 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
887 int DISK::get_track_size()
890 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
892 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
896 double DISK::get_usec_per_track()
898 return 1000000.0 / (get_rpm() / 60.0);
901 double DISK::get_usec_per_bytes(int bytes)
903 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
906 int DISK::get_bytes_per_usec(double usec)
908 return (int)(usec / get_usec_per_bytes(1) + 0.5);
911 bool DISK::check_media_type()
915 return (media_type == MEDIA_TYPE_2D);
917 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
919 return (media_type == MEDIA_TYPE_2HD);
921 return (media_type == MEDIA_TYPE_144);
923 return true; // always okay
928 // teledisk image decoder
931 this teledisk image decoder is based on:
933 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
934 LZSS coded by Haruhiko OKUMURA
935 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
936 Edited and translated to English by Kenji RIKITAKE
940 #define COPYBUFFER(src, size) { \
941 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
944 memcpy(buffer + file_size.d, (src), (size)); \
945 file_size.d += (size); \
948 bool DISK::teledisk_to_d88()
958 // check teledisk header
959 fi->Fseek(0, FILEIO_SEEK_SET);
960 fi->Fread(&hdr, sizeof(td_hdr_t), 1);
961 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
962 // decompress to the temporary file
963 FILEIO* fo = new FILEIO();
964 if(!fo->Fopen(temp_path, FILEIO_WRITE_BINARY)) {
971 if((rd = decode(obuf, 512)) > 0) {
972 fo->Fwrite(obuf, rd, 1);
980 // reopen the temporary file
982 if(!fi->Fopen(temp_path, FILEIO_READ_BINARY)) {
986 if(hdr.flag & 0x80) {
988 fi->Fread(&cmt, sizeof(td_cmt_t), 1);
989 fi->Fseek(cmt.len, FILEIO_SEEK_CUR);
996 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
997 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
998 d88_hdr.protect = 0; // non-protected
999 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1002 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1003 fi->Fread(&trk, sizeof(td_trk_t), 1);
1004 while(trk.nsec != 0xff) {
1005 d88_hdr.trkptr[trkcnt++] = trkptr;
1006 if(hdr.sides == 1) {
1007 d88_hdr.trkptr[trkcnt++] = trkptr;
1010 // read sectors in this track
1011 for(int i = 0; i < trk.nsec; i++) {
1012 uint8 buf[2048], dst[2048];
1013 memset(buf, 0, sizeof(buf));
1014 memset(dst, 0, sizeof(dst));
1016 // read sector header
1017 fi->Fread(&sct, sizeof(td_sct_t), 1);
1019 // create d88 sector header
1020 memset(&d88_sct, 0, sizeof(d88_sct_t));
1025 d88_sct.nsec = trk.nsec;
1026 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1027 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1028 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1029 d88_sct.size = secsize[sct.n & 3];
1031 // create sector image
1032 if(sct.ctrl != 0x10) {
1033 // read sector source
1034 int len = fi->Fgetc();
1035 len += fi->Fgetc() * 256 - 1;
1036 int flag = fi->Fgetc(), d = 0;
1037 fi->Fread(buf, len, 1);
1041 memcpy(dst, buf, len);
1042 } else if(flag == 1) {
1044 len2.read_2bytes_le_from(buf);
1049 } else if(flag == 2) {
1050 for(int s = 0; s < len;) {
1051 int type = buf[s++];
1052 int len2 = buf[s++];
1055 dst[d++] = buf[s++];
1057 } else if(type < 5) {
1063 for(int j = 0; j < n; j++) {
1067 for(int j = 0; j < n; j++) {
1072 break; // unknown type
1076 break; // unknown flag
1083 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1084 COPYBUFFER(dst, d88_sct.size);
1085 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1088 fi->Fread(&trk, sizeof(td_trk_t), 1);
1090 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1091 d88_hdr.size = trkptr;
1092 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1096 int DISK::next_word()
1098 if(ibufndx >= ibufcnt) {
1099 ibufndx = ibufcnt = 0;
1100 memset(inbuf, 0, 512);
1101 for(int i = 0; i < 512; i++) {
1102 int d = fi->Fgetc();
1113 while(getlen <= 8) {
1114 getbuf |= inbuf[ibufndx++] << (8 - getlen);
1122 if(next_word() < 0) {
1128 return (i < 0) ? 1 : 0;
1131 int DISK::get_byte()
1133 if(next_word() != 0) {
1143 void DISK::start_huff()
1146 for(i = 0; i < N_CHAR; i++) {
1148 son[i] = i + TABLE_SIZE;
1149 prnt[i + TABLE_SIZE] = i;
1152 while(j <= ROOT_POSITION) {
1153 freq[j] = freq[i] + freq[i + 1];
1155 prnt[i] = prnt[i + 1] = j;
1158 freq[TABLE_SIZE] = 0xffff;
1159 prnt[ROOT_POSITION] = 0;
1162 void DISK::reconst()
1166 for(i = 0; i < TABLE_SIZE; i++) {
1167 if(son[i] >= TABLE_SIZE) {
1168 freq[j] = (freq[i] + 1) / 2;
1173 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1175 f = freq[j] = freq[i] + freq[k];
1176 for(k = j - 1; f < freq[k]; k--);
1179 memmove(&freq[k + 1], &freq[k], l);
1181 memmove(&son[k + 1], &son[k], l);
1184 for(i = 0; i < TABLE_SIZE; i++) {
1185 if((k = son[i]) >= TABLE_SIZE) {
1188 prnt[k] = prnt[k + 1] = i;
1193 void DISK::update(int c)
1196 if(freq[ROOT_POSITION] == MAX_FREQ) {
1199 c = prnt[c + TABLE_SIZE];
1202 if(k > freq[l = c + 1]) {
1203 while(k > freq[++l]);
1209 if(i < TABLE_SIZE) {
1215 if(j < TABLE_SIZE) {
1222 while((c = prnt[c]) != 0);
1225 short DISK::decode_char()
1228 uint16 c = son[ROOT_POSITION];
1229 while(c < TABLE_SIZE) {
1230 if((ret = get_bit()) < 0) {
1241 short DISK::decode_position()
1245 if((bit = get_byte()) < 0) {
1249 c = (uint16)d_code[i] << 6;
1252 if((bit = get_bit()) < 0) {
1257 return (c | i & 0x3f);
1260 void DISK::init_decode()
1262 ibufcnt= ibufndx = bufcnt = getbuf = 0;
1265 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1268 ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1271 int DISK::decode(uint8 *buf, int len)
1275 for(count = 0; count < len;) {
1277 if((c = decode_char()) < 0) {
1281 *(buf++) = (uint8)c;
1282 text_buf[ptr++] = (uint8)c;
1283 ptr &= (STRING_BUFFER_SIZE - 1);
1286 if((pos = decode_position()) < 0) {
1289 bufpos = (ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1290 bufcnt = c - 255 + THRESHOLD;
1294 while(bufndx < bufcnt && count < len) {
1295 c = text_buf[(bufpos + bufndx) & (STRING_BUFFER_SIZE - 1)];
1296 *(buf++) = (uint8)c;
1298 text_buf[ptr++] = (uint8)c;
1299 ptr &= (STRING_BUFFER_SIZE - 1);
1302 if(bufndx >= bufcnt) {
1303 bufndx = bufcnt = 0;
1310 // imagedisk image decoder
1312 bool DISK::imagedisk_to_d88()
1319 fi->Fseek(0, FILEIO_SEEK_SET);
1321 while((tmp = fi->Fgetc()) != 0x1a) {
1330 // create d88 header
1331 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1332 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
1333 d88_hdr.protect = 0; // non-protected
1334 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1337 int trkptr = sizeof(d88_hdr_t);
1338 int trkcnt = 0, mode;
1340 for(int t = 0; t < 164; t++) {
1341 // check end of file
1342 if(fi->Fread(&trk, sizeof(imd_trk_t), 1) != 1) {
1347 // check track header
1349 mode = trk.mode % 3; // 0=500kbps, 1=300kbps, 2=250kbps
1354 d88_hdr.trkptr[t] = trkptr;
1357 uint8 c[64], h[64], r[64];
1358 fi->Fread(r, trk.nsec, 1);
1359 if(trk.head & 0x80) {
1360 fi->Fread(c, trk.nsec, 1);
1362 memset(c, trk.cyl, sizeof(c));
1364 if(trk.head & 0x40) {
1365 fi->Fread(h, trk.nsec, 1);
1367 memset(h, trk.head & 1, sizeof(h));
1370 // read sectors in this track
1371 for(int i = 0; i < trk.nsec; i++) {
1372 // create d88 sector header
1373 int sectype = fi->Fgetc();
1377 memset(&d88_sct, 0, sizeof(d88_sct_t));
1381 d88_sct.n = trk.size;
1382 d88_sct.nsec = trk.nsec;
1383 d88_sct.dens = (trk.mode < 3) ? 0x40 : 0;
1384 d88_sct.del = (sectype == 3 || sectype == 4 || sectype == 7 || sectype == 8) ? 0x10 : 0;
1385 d88_sct.stat = (sectype == 5 || sectype == 6 || sectype == 7 || sectype == 8) ? 0xb0 : d88_sct.del;
1386 d88_sct.size = secsize[trk.size & 7];
1388 // create sector image
1390 if(sectype == 1 || sectype == 3 || sectype == 5 || sectype == 7) {
1392 fi->Fread(dst, d88_sct.size, 1);
1393 } else if(sectype == 2 || sectype == 4 || sectype == 6 || sectype == 8) {
1395 int tmp = fi->Fgetc();
1396 memset(dst, tmp, d88_sct.size);
1402 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1403 COPYBUFFER(dst, d88_sct.size);
1404 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1407 d88_hdr.type = (mode == 0) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1408 d88_hdr.size = trkptr;
1409 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1413 // cpdread image decoder (from MESS formats/dsk_dsk.c)
1415 bool DISK::cpdread_to_d88(int extended)
1421 // get cylinder number and side number
1422 memcpy(tmp_buffer, buffer, file_size.d);
1423 int ncyl = tmp_buffer[0x30];
1424 int nside = tmp_buffer[0x31];
1429 // create d88 header
1430 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1431 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDRead");
1432 d88_hdr.protect = 0; // non-protected
1433 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1436 int trkofs = 0x100, trkofs_ptr = 0x34;
1437 int trkptr = sizeof(d88_hdr_t);
1439 for(int c = 0; c < ncyl; c++) {
1440 for(int h = 0; h < nside; h++) {
1441 // read sectors in this track
1442 uint8 *track_info = tmp_buffer + trkofs;
1443 int cyl = track_info[0x10];
1444 int side = track_info[0x11];
1445 int nsec = track_info[0x15];
1446 int size = 1 << (track_info[0x14] + 7); // standard
1447 int sctofs = trkofs + 0x100;
1451 d88_hdr.trkptr[2 * cyl] = d88_hdr.trkptr[2 * cyl + 1] = trkptr;
1453 d88_hdr.trkptr[2 * cyl + side] = trkptr;
1455 for(int s = 0; s < nsec; s++) {
1457 uint8 *sector_info = tmp_buffer + trkofs + 0x18 + s * 8;
1459 size = sector_info[6] + sector_info[7] * 256;
1462 // create d88 sector header
1463 memset(&d88_sct, 0, sizeof(d88_sct_t));
1464 d88_sct.c = sector_info[0];
1465 d88_sct.h = sector_info[1];
1466 d88_sct.r = sector_info[2];
1467 d88_sct.n = sector_info[3];
1468 d88_sct.nsec = nsec;
1470 d88_sct.del = (sector_info[5] == 0xb2) ? 0x10 : 0;
1471 d88_sct.stat = (sector_info[5] == 0xb5) ? 0xb0 : d88_sct.del;
1472 d88_sct.size = size;
1475 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1476 COPYBUFFER(tmp_buffer + sctofs, size);
1477 trkptr += sizeof(d88_sct_t) + size;
1483 trkofs += tmp_buffer[trkofs_ptr++] * 256;
1485 trkofs += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
1489 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
1490 d88_hdr.size = trkptr;
1491 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1495 // solid image decoder
1497 bool DISK::solid_to_d88(int type, int ncyl, int nside, int nsec, int size)
1505 // create d88 header
1506 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1507 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "STANDARD");
1508 d88_hdr.protect = 0; // non-protected
1509 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
1511 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1514 for(int i = 0; i < 8; i++) {
1515 if(size == (128 << i)) {
1522 int trkptr = sizeof(d88_hdr_t);
1523 for(int c = 0; c < ncyl; c++) {
1524 for(int h = 0; h < nside; h++) {
1525 d88_hdr.trkptr[t++] = trkptr;
1528 d88_hdr.trkptr[t++] = trkptr;
1531 // read sectors in this track
1532 for(int s = 0; s < nsec; s++) {
1533 // create d88 sector header
1534 memset(&d88_sct, 0, sizeof(d88_sct_t));
1539 d88_sct.nsec = nsec;
1543 d88_sct.size = size;
1545 // create sector image
1547 memset(dst, 0xe5, sizeof(dst));
1548 fi->Fread(dst, size, 1);
1551 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1552 COPYBUFFER(dst, size);
1553 trkptr += sizeof(d88_sct_t) + size;
1557 d88_hdr.size = trkptr;
1558 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1562 #define STATE_VERSION 5
1564 void DISK::save_state(FILEIO* state_fio)
1566 state_fio->FputUint32(STATE_VERSION);
1568 state_fio->Fwrite(buffer, sizeof(buffer), 1);
1569 state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
1570 state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
1571 state_fio->FputUint32(file_size.d);
1572 state_fio->FputInt32(file_bank);
1573 state_fio->FputUint32(crc32);
1574 state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
1575 state_fio->FputBool(inserted);
1576 state_fio->FputBool(ejected);
1577 state_fio->FputBool(write_protected);
1578 state_fio->FputBool(changed);
1579 state_fio->FputUint8(media_type);
1580 state_fio->FputBool(is_solid_image);
1581 state_fio->FputBool(is_fdi_image);
1582 state_fio->FputInt32(is_special_disk);
1583 state_fio->Fwrite(track, sizeof(track), 1);
1584 state_fio->FputInt32(sector_num.sd);
1585 state_fio->FputBool(invalid_format);
1586 state_fio->FputBool(no_skew);
1587 state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
1588 state_fio->Fwrite(id_position, sizeof(id_position), 1);
1589 state_fio->Fwrite(data_position, sizeof(data_position), 1);
1590 state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
1591 state_fio->FputInt32(sector_size.sd);
1592 state_fio->Fwrite(id, sizeof(id), 1);
1593 state_fio->FputUint8(density);
1594 state_fio->FputBool(deleted);
1595 state_fio->FputBool(addr_crc_error);
1596 state_fio->FputBool(data_crc_error);
1597 state_fio->FputUint8(drive_type);
1598 state_fio->FputInt32(drive_rpm);
1599 state_fio->FputBool(drive_mfm);
1602 bool DISK::load_state(FILEIO* state_fio)
1604 if(state_fio->FgetUint32() != STATE_VERSION) {
1607 state_fio->Fread(buffer, sizeof(buffer), 1);
1608 state_fio->Fread(orig_path, sizeof(orig_path), 1);
1609 state_fio->Fread(dest_path, sizeof(dest_path), 1);
1610 file_size.d = state_fio->FgetUint32();
1611 file_bank = state_fio->FgetInt32();
1612 crc32 = state_fio->FgetUint32();
1613 state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
1614 inserted = state_fio->FgetBool();
1615 ejected = state_fio->FgetBool();
1616 write_protected = state_fio->FgetBool();
1617 changed = state_fio->FgetBool();
1618 media_type = state_fio->FgetUint8();
1619 is_solid_image = state_fio->FgetBool();
1620 is_fdi_image = state_fio->FgetBool();
1621 is_special_disk = state_fio->FgetInt32();
1622 state_fio->Fread(track, sizeof(track), 1);
1623 sector_num.sd = state_fio->FgetInt32();
1624 invalid_format = state_fio->FgetBool();
1625 no_skew = state_fio->FgetBool();
1626 state_fio->Fread(sync_position, sizeof(sync_position), 1);
1627 state_fio->Fread(id_position, sizeof(id_position), 1);
1628 state_fio->Fread(data_position, sizeof(data_position), 1);
1629 int offset = state_fio->FgetInt32();
1630 sector = (offset != -1) ? buffer + offset : NULL;
1631 sector_size.sd = state_fio->FgetInt32();
1632 state_fio->Fread(id, sizeof(id), 1);
1633 density = state_fio->FgetUint8();
1634 deleted = state_fio->FgetBool();
1635 addr_crc_error = state_fio->FgetBool();
1636 data_crc_error = state_fio->FgetBool();
1637 drive_type = state_fio->FgetUint8();
1638 drive_rpm = state_fio->FgetInt32();
1639 drive_mfm = state_fio->FgetBool();