2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
15 #include "../fileio.h"
18 #define local_path(x) create_local_path(x)
20 #define local_path(x) (x)
26 static const uint16_t crc_table[256] = {
27 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
28 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
29 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
30 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
31 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
32 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
33 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
34 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
35 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
36 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
37 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
38 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
39 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
40 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
41 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
42 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
45 static const int secsize[8] = {
46 128, 256, 512, 1024, 2048, 4096, 8192, 16384
49 static uint8_t tmp_buffer[DISK_BUFFER_SIZE];
51 static const fd_format_t fd_formats_base[] = {
52 { MEDIA_TYPE_2D, 35, 1, 16, 128, FM }, // 1S 70KB
53 { MEDIA_TYPE_2D, 35, 2, 16, 128, FM }, // 2S 140KB
54 { MEDIA_TYPE_2DD, 77, 1, 26, 128, FM }, // 1S 250KB
55 { MEDIA_TYPE_2D, 40, 1, 8, 512, MFM }, // 1D 160KB
56 { MEDIA_TYPE_2D, 40, 1, 9, 512, MFM }, // 1D 180KB
57 { MEDIA_TYPE_2D, 40, 1, 10, 512, MFM }, // 1D 200KB
58 //#if defined(SUPPORT_MEDIA_TYPE_1DD)
59 // { MEDIA_TYPE_2DD, 70, 1, 8, 512, MFM }, // 1DD 280KB
60 // { MEDIA_TYPE_2DD, 70, 1, 9, 512, MFM }, // 1DD 315KB
61 // { MEDIA_TYPE_2DD, 70, 1, 10, 512, MFM }, // 1DD 350KB
62 // { MEDIA_TYPE_2DD, 80, 1, 8, 512, MFM }, // 1DD 320KB
63 // { MEDIA_TYPE_2DD, 80, 1, 9, 512, MFM }, // 1DD 360KB
64 // { MEDIA_TYPE_2DD, 80, 1, 10, 512, MFM }, // 1DD 400KB
66 { MEDIA_TYPE_2D, 35, 2, 8, 512, MFM }, // 2D 280KB
67 { MEDIA_TYPE_2D, 35, 2, 9, 512, MFM }, // 2D 315KB
68 { MEDIA_TYPE_2D, 35, 2, 10, 512, MFM }, // 2D 350KB
69 { MEDIA_TYPE_2D, 40, 2, 8, 512, MFM }, // 2D 320KB
70 { MEDIA_TYPE_2D, 40, 2, 9, 512, MFM }, // 2D 360KB
71 { MEDIA_TYPE_2D, 40, 2, 10, 512, MFM }, // 2D 400KB
73 { MEDIA_TYPE_2DD, 80, 2, 8, 512, MFM }, // 2DD 640KB
74 { MEDIA_TYPE_2DD, 80, 2, 9, 512, MFM }, // 2DD 720KB
75 { MEDIA_TYPE_2DD, 81, 2, 9, 512, MFM }, // 2DD 729KB, ASCII MSX
76 { MEDIA_TYPE_2DD, 80, 2, 10, 512, MFM }, // 2DD 800KB
77 { MEDIA_TYPE_2HD, 77, 2, 26, 256, MFM }, // 2HD 1001KB, MITSUBISHI/IBM
78 { MEDIA_TYPE_2HD, 80, 2, 15, 512, MFM }, // 2HC 1200KB, TOSHIBA/IBM
79 { MEDIA_TYPE_2HD, 77, 2, 8, 1024, MFM }, // 2HD 1232KB, NEC
80 { MEDIA_TYPE_144, 80, 2, 18, 512, MFM }, // 2HD 1440KB
81 { MEDIA_TYPE_144, 80, 2, 21, 512, MFM }, // 2HD 1680KB
82 { MEDIA_TYPE_144, 82, 2, 21, 512, MFM }, // 2HD 1722KB
83 { MEDIA_TYPE_144, 80, 2, 36, 512, MFM }, // 2ED 2880KB
87 #define IS_VALID_TRACK(offset) ((offset) >= 0x20 && (offset) < sizeof(buffer))
89 void DISK::setup_fd_formats(void)
93 memset(fd_formats, 0, sizeof(fd_formats));
94 #if !defined(_ANY2D88)
96 if(osd->check_feature(_T("_SC3000"))) {
99 nt = { MEDIA_TYPE_2D, 40, 1, 16, 256, MFM }; // 1D 160KB
100 } else if(osd->check_feature(_T("SMC70")) || osd->check_feature(_T("_SMC777"))) {
103 nt = { MEDIA_TYPE_2DD, 70, 1, 16, 256, MFM }; // 1DD 280KB
104 } else if (osd->check_feature(_T("_X1")) || osd->check_feature(_T("_X1TWIN"))) {
107 nt = { MEDIA_TYPE_2D, 40, 2, 16, 256, MFM }; // 2D 320KB
108 } else if(osd->check_feature(_T("_X1TURBO")) || osd->check_feature(_T("_X1TURBOZ"))) {
112 nt = { MEDIA_TYPE_2D, 40, 2, 16, 256, MFM }; // 2D 320KB
113 } else if(osd->check_feature(_T("_M5"))) {
116 nt = { MEDIA_TYPE_2D, 40, 2, 18, 256, MFM }; // 2D 360KB
117 } else if(osd->check_feature(_T("_MZ80B")) || osd->check_feature(_T("_MZ2000")) ||
118 osd->check_feature(_T("_MZ2200")) || osd->check_feature(_T("_MZ2500"))) {
121 nt = { MEDIA_TYPE_2DD, 80, 2, 16, 256, MFM }; // 2DD 640KB
122 } else if (osd->check_feature(_T("_YIS"))) {
125 nt = { MEDIA_TYPE_2DD, 80, 1, 16, 256, MFM }; // 1DD 320KB
127 if(osd->check_feature(_T("_FM7")) || osd->check_feature(_T("_FM8"))) {
130 } else if(osd->check_feature(_T("_FM77_VARIANTS"))) {
134 } else if(osd->check_feature(_T("_FM77AV_VARIANTS"))) {
139 if(osd->check_feature(_T("_FM77AV40")) || osd->check_feature(_T("_FM77AV40EX")) ||
140 osd->check_feature(_T("_FM77AV40SX")) || osd->check_feature(_T("_FM77AV20")) ||
141 osd->check_feature(_T("_FM77AV20EX"))) {
142 type_fm77av_2dd = true;
145 if(osd->check_feature(_T("SUPPORT_MEDIA_TYPE_1DD"))) {
148 if(osd->check_feature(_T("_ANY2D88"))) {
156 memcpy(&fd_formats[1], fd_formats_base, sizeof(fd_formats_base));
158 memcpy(&fd_formats[0], fd_formats_base, sizeof(fd_formats_base));
162 void DISK::open(const _TCHAR* file_path, int bank)
164 // check current disk image
166 if(_tcsicmp(orig_path, file_path) == 0 && file_bank == bank) {
174 memset(buffer, 0, sizeof(buffer));
176 write_protected = false;
177 media_type = MEDIA_TYPE_UNK;
179 is_solid_image = is_fdi_image = is_1dd_image = false;
180 trim_required = false;
181 track_mfm = drive_mfm;
184 FILEIO *fio = new FILEIO();
185 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
186 my_tcscpy_s(orig_path, _MAX_PATH, file_path);
187 my_tcscpy_s(dest_path, _MAX_PATH, file_path);
189 file_size.d = fio->FileLength();
190 fio->Fseek(0, FILEIO_SEEK_SET);
192 if(check_file_extension(file_path, _T(".d88")) || check_file_extension(file_path, _T(".d77")) || check_file_extension(file_path, _T(".1dd"))) {
195 for(int i = 0; i < bank; i++) {
196 fio->Fseek(offset + 0x1c, SEEK_SET);
197 offset += fio->FgetUint32_LE();
199 fio->Fseek(offset + 0x1c, FILEIO_SEEK_SET);
200 file_size.d = fio->FgetUint32_LE();
201 fio->Fseek(offset, FILEIO_SEEK_SET);
202 fio->Fread(buffer, file_size.d, 1);
204 if(check_file_extension(file_path, _T(".1dd"))) {
206 media_type = MEDIA_TYPE_2DD;
208 inserted = changed = true;
209 // trim_required = true;
211 // fix sector number from big endian to little endian
212 for(int trkside = 0; trkside < 164; trkside++) {
214 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
216 if(!IS_VALID_TRACK(offset.d)) {
219 uint8_t* t = buffer + offset.d;
220 pair_t sector_num, data_size;
221 sector_num.read_2bytes_le_from(t + 4);
222 bool is_be = (sector_num.b.l == 0 && sector_num.b.h >= 4);
224 sector_num.read_2bytes_be_from(t + 4);
225 sector_num.write_2bytes_le_to(t + 4);
227 for(int i = 0; i < sector_num.sd; i++) {
229 sector_num.write_2bytes_le_to(t + 4);
231 data_size.read_2bytes_le_from(t + 14);
232 t += data_size.sd + 0x10;
235 } else if(check_file_extension(file_path, _T(".td0"))) {
238 if(teledisk_to_d88(fio)) {
239 inserted = changed = true;
240 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
243 // failed to convert the disk image
245 } else if(check_file_extension(file_path, _T(".imd"))) {
248 if(imagedisk_to_d88(fio)) {
249 inserted = changed = true;
250 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
253 // failed to convert the disk image
255 } else if(check_file_extension(file_path, _T(".dsk"))) {
258 if(cpdread_to_d88(fio)) {
259 inserted = changed = true;
260 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
263 // failed to convert the disk image
265 } else if(check_file_extension(file_path, _T(".nfd"))) {
266 // T98-NEXT nfd r0/r1 image for NEC PC-98x1 series
268 if(nfdr0_to_d88(fio) || nfdr1_to_d88(fio)) {
269 inserted = changed = true;
270 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
273 // failed to convert the disk image
275 } else if(check_file_extension(file_path, _T(".fdi"))) {
276 // Anex86 fdi image for NEC PC-98x1 series
277 if(file_size.d == 4096 + 77 * 2 * 8 * 1024) {
279 fio->Fread(fdi_header, 4096, 1);
280 if(solid_to_d88(fio, MEDIA_TYPE_2HD, 77, 2, 8, 1024, true)) {
281 inserted = changed = is_solid_image = is_fdi_image = true;
284 // failed to convert the disk image
286 } else if(file_size.d == 4096 + 80 * 2 * 15 * 512) {
288 fio->Fread(fdi_header, 4096, 1);
289 if(solid_to_d88(fio, MEDIA_TYPE_2HD, 80, 2, 15, 512, true)) {
290 inserted = changed = is_solid_image = is_fdi_image = true;
293 // failed to convert the disk image
295 } else if(file_size.d == 4096 + 80 * 2 * 18 * 512) {
297 fio->Fread(fdi_header, 4096, 1);
298 if(solid_to_d88(fio, MEDIA_TYPE_144, 80, 2, 18, 512, true)) {
299 inserted = changed = is_solid_image = is_fdi_image = true;
302 // failed to convert the disk image
304 } else if(file_size.d == 4096 + 77 * 2 * 26 * 256) {
306 fio->Fread(fdi_header, 4096, 1);
307 if(solid_to_d88(fio, MEDIA_TYPE_2HD, 77, 2, 26, 256, true)) {
308 inserted = changed = is_solid_image = is_fdi_image = true;
311 // failed to convert the disk image
313 } else if(file_size.d == 4096 + 80 * 2 * 9 * 512) {
315 fio->Fread(fdi_header, 4096, 1);
316 if(solid_to_d88(fio, MEDIA_TYPE_2DD, 80, 2, 9, 512, true)) {
317 inserted = changed = is_solid_image = is_fdi_image = true;
320 // failed to convert the disk image
322 } else if(file_size.d == 4096 + 80 * 2 * 8 * 512) {
324 fio->Fread(fdi_header, 4096, 1);
325 if(solid_to_d88(fio, MEDIA_TYPE_2DD, 80, 2, 8, 512, true)) {
326 inserted = changed = is_solid_image = is_fdi_image = true;
329 // failed to convert the disk image
332 } else if(check_file_extension(file_path, _T(".hdm")) && file_size.d == 77 * 2 * 8 * 1024) {
333 // BKDSK hdm image for NEC PC-98x1 series
335 if(solid_to_d88(fio, MEDIA_TYPE_2HD, 77, 2, 8, 1024, true)) {
336 inserted = changed = is_solid_image = true;
339 // failed to convert the disk image
341 } else if(check_file_extension(file_path, _T(".hd5")) && file_size.d == 80 * 2 * 15 * 512) {
342 // BKDSK hd5 image for NEC PC-98x1 series
344 if(solid_to_d88(fio, MEDIA_TYPE_2HD, 80, 2, 15, 512, true)) {
345 inserted = changed = is_solid_image = true;
348 // failed to convert the disk image
350 } else if(check_file_extension(file_path, _T(".hd4")) && file_size.d == 80 * 2 * 18 * 512) {
351 // BKDSK hd4 image for NEC PC-98x1 series
353 if(solid_to_d88(fio, MEDIA_TYPE_144, 80, 2, 18, 512, true)) {
354 inserted = changed = is_solid_image = true;
357 // failed to convert the disk image
359 } else if(check_file_extension(file_path, _T(".hdb")) && file_size.d == 77 * 2 * 26 * 256) {
360 // BKDSK hdb image for NEC PC-98x1 series
362 if(solid_to_d88(fio, MEDIA_TYPE_2HD, 77, 2, 26, 256, true)) {
363 inserted = changed = is_solid_image = true;
366 // failed to convert the disk image
368 } else if(check_file_extension(file_path, _T(".dd9")) && file_size.d == 80 * 2 * 9 * 512) {
369 // BKDSK dd9 image for NEC PC-98x1 series
371 if(solid_to_d88(fio, MEDIA_TYPE_2DD, 80, 2, 9, 512, true)) {
372 inserted = changed = is_solid_image = true;
375 // failed to convert the disk image
377 } else if(check_file_extension(file_path, _T(".dd6")) && file_size.d == 80 * 2 * 8 * 512) {
378 // BKDSK dd6 image for NEC PC-98x1 series
380 if(solid_to_d88(fio, MEDIA_TYPE_2DD, 80, 2, 8, 512, true)) {
381 inserted = changed = is_solid_image = true;
384 // failed to convert the disk image
386 } else if(check_file_extension(file_path, _T(".xdf")) && file_size.d == 77 * 2 * 8 * 1024) {
387 // EX68 xdf image for SHARP X680x0 series
389 if(solid_to_d88(fio, MEDIA_TYPE_2HD, 77, 2, 8, 1024, true)) {
390 inserted = changed = is_solid_image = true;
393 // failed to convert the disk image
395 } else if(check_file_extension(file_path, _T(".2d")) && file_size.d == 40 * 2 * 16 * 256) {
396 // 2d image for SHARP X1 series
398 if(solid_to_d88(fio, MEDIA_TYPE_2D, 40, 2, 16, 256, true)) {
399 inserted = changed = is_solid_image = true;
402 // failed to convert the disk image
404 } else if(check_file_extension(file_path, _T(".sf7")) && file_size.d == 40 * 1 * 16 * 256) {
405 // sf7 image for SEGA SC-3000 + SF-7000
407 if(solid_to_d88(fio, MEDIA_TYPE_2D, 40, 1, 16, 256, true)) {
408 inserted = changed = is_solid_image = true;
411 // failed to convert the disk image
413 } else if(check_file_extension(file_path, _T(".img")) && file_size.d == 70 * 1 * 16 * 256) {
414 // img image for SONY SMC-70/777 series
416 if(solid_to_d88(fio, MEDIA_TYPE_2DD, 70, 1, 16, 256, true)) {
417 inserted = changed = is_solid_image = true;
420 // failed to convert the disk image
424 // check solid image file format
425 for(int i = 0;; i++) {
426 const fd_format_t *p = &fd_formats[i];
430 if(file_size.d == (uint32_t)(p->ncyl * p->nside * p->nsec * p->size)) {
431 fio->Fseek(0, FILEIO_SEEK_SET);
434 int nside = p->nside;
437 //#if defined(SUPPORT_MEDIA_TYPE_1DD)
439 if(type == MEDIA_TYPE_2D && nside == 2 && p->mfm) {
440 type = MEDIA_TYPE_2DD;
444 } else if(type_any2d88) {
445 //#elif defined(_ANY2D88)
446 if(open_as_1dd && type == MEDIA_TYPE_2D && nside == 2 && p->mfm) {
447 type = MEDIA_TYPE_2DD;
451 if(open_as_256 && (size == 512 || size == 1024)) {
458 // if(solid_to_d88(fio, p->type, p->ncyl, p->nside, p->nsec, p->size, p->mfm)) {
459 if(solid_to_d88(fio, type, ncyl, nside, nsec, size, p->mfm)) {
460 inserted = changed = is_solid_image = true;
463 // failed to convert the disk image
471 if(fio->IsOpened()) {
477 // check loaded image
480 if(media_type == MEDIA_TYPE_UNK) {
481 if((media_type = buffer[0x1b]) == MEDIA_TYPE_2HD) {
482 // check 1.2MB or 1.44MB
483 for(int trkside = 0; trkside < 164; trkside++) {
485 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
487 if(!IS_VALID_TRACK(offset.d)) {
491 uint8_t *t = buffer + offset.d;
492 pair_t sector_num, data_size;
493 sector_num.read_2bytes_le_from(t + 4);
494 data_size.read_2bytes_le_from(t + 14);
496 if(sector_num.sd >= 18 && data_size.sd == 512) {
497 media_type = MEDIA_TYPE_144;
507 for(int trk = 0; trk < 82; trk++) {
508 for(int side = 0; side < 2; side++) {
509 int trkside = trk * 2 + side;
511 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
513 if(IS_VALID_TRACK(offset.d)) {
514 valid_side |= (1 << side);
517 if(valid_side == 3) break;
519 // FIXME: unformat disk is recognized as two side
520 two_side = (valid_side != 1);
522 // fix write protect flag
523 if(buffer[0x1a] != 0) {
525 write_protected = true;
528 // get crc32 for midification check
529 orig_file_size = file_size.d;
530 orig_crc32 = get_crc32(buffer, file_size.d);
532 // check special disk image
533 //#if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
535 // FIXME: ugly patch for FM-7 Gambler Jiko Chuushin Ha, DEATH FORCE and Psy-O-Blade
536 if(media_type == MEDIA_TYPE_2D) {
538 pair_t offset, sector_num, data_size;
539 offset.read_4bytes_le_from(buffer + 0x20);
541 if(IS_VALID_TRACK(offset.d)) {
542 // check the sector (c,h,r,n) = (0,0,7,1) or (0,0,f7,2)
543 uint8_t* t = buffer + offset.d;
544 sector_num.read_2bytes_le_from(t + 4);
545 for(int _i = 0; _i < sector_num.sd; _i++) {
546 data_size.read_2bytes_le_from(t + 14);
547 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 7 && t[3] == 1) {
548 /* Type 1: Sec07, +$50- "1989/09/12 ... "*/
549 static const uint8_t gamblerfm_1[] = {
550 0x31, 0x39, 0x38, 0x39, 0x2f, 0x30, 0x39, 0x2f,
551 0x31, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552 0x28, 0x43, 0x29, 0x47, 0x41, 0x4d, 0x45, 0x41,
553 0x52, 0x54, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x20, 0x20, 0x20, 0x59, 0x45, 0x4c, 0x4c, 0x4f,
555 0x57, 0x48, 0x4f, 0x52, 0x4e, 0x00, 0x00, 0x00,
556 0x20, 0x20, 0x20, 0x4b, 0x4f, 0x55, 0x44, 0x41,
557 0x4e, 0x53, 0x59, 0x41, 0x20, 0x59, 0x4f, 0x55,
558 0x4e, 0x47, 0x2d, 0x4d, 0x41, 0x47, 0x41, 0x5a,
559 0x49, 0x4e, 0x45, 0x00
561 /* Type 2: Sec07, +$30- */
562 static const uint8_t gamblerfm_2[] = {
563 0xb7, 0xde, 0xad, 0xdc, 0xdd, 0xcc, 0xde, 0xd7,
564 0xb1, 0x20, 0xbc, 0xde, 0xba, 0xc1, 0xad, 0xb3,
567 if(memcmp((void *)(t + 0x50), gamblerfm_1, sizeof(gamblerfm_1)) == 0) {
568 is_special_disk = SPECIAL_DISK_FM7_GAMBLER;
571 if(memcmp((void *)(t + 0x30), gamblerfm_2, sizeof(gamblerfm_2)) == 0) {
572 is_special_disk = SPECIAL_DISK_FM7_GAMBLER;
575 } else if(data_size.sd == 0x200 && t[0] == 0 && t[1] == 0 && t[2] == 0xf7 && t[3] == 2) {
576 //"DEATHFORCE/77AV" + $f7*17 + $00 + $00
577 static const uint8_t deathforce[] ={
578 0x44, 0x45, 0x41, 0x54, 0x48, 0x46, 0x4f, 0x52,
579 0x43, 0x45, 0x2f, 0x37, 0x37, 0x41, 0x56, 0xf7,
580 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
581 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
584 if(memcmp((void *)(t + 0x10), deathforce, sizeof(deathforce)) == 0) {
585 is_special_disk = SPECIAL_DISK_FM7_DEATHFORCE;
588 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 5 && t[3] == 1) {
589 //$00 * 16 + $00 + "Protected by N & A (SUPER HACKER COMBI)
590 //Can you found CHECK-ROUTINES ?Can you crack these protect ?
592 static const uint8_t xanadu2fm_d_1[] ={
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 static const uint8_t xanadu2fm_d_2[] = {
597 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x65,
598 0x64, 0x20, 0x62, 0x79, 0x20, 0x20, 0x4E, 0x20,
599 0x26, 0x20, 0x41, 0x20, 0x28, 0x53, 0x55, 0x50,
600 0x45, 0x52, 0x20, 0x48, 0x41, 0x43, 0x4B, 0x45,
601 0x52, 0x20, 0x43, 0x4F, 0x4D, 0x42, 0x49, 0x29,
602 0x43, 0x61, 0x6E, 0x20, 0x79, 0x6F, 0x75, 0x20,
603 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x43, 0x48,
604 0x45, 0x43, 0x4B, 0x2D, 0x52, 0x4F, 0x55, 0x54,
605 0x49, 0x4E, 0x45, 0x53, 0x20, 0x3F, 0x43, 0x61,
606 0x6E, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x63, 0x72,
607 0x61, 0x63, 0x6B, 0x20, 0x74, 0x68, 0x65, 0x73,
608 0x65, 0x20, 0x70, 0x72, 0x6F, 0x74, 0x65, 0x63,
609 0x74, 0x20, 0x3F, 0x67, 0x6F, 0x6F, 0x64, 0x20,
610 0x62, 0x79, 0x65, 0x20, 0x21, 0x6F, 0x75, 0x20,
612 if(memcmp((void *)(t + 0x10 + 0x60), xanadu2fm_d_1, sizeof(xanadu2fm_d_1)) == 0) {
613 if(memcmp((void *)(t + 0x10 + 0x70), xanadu2fm_d_2, sizeof(xanadu2fm_d_2)) == 0) {
614 is_special_disk = SPECIAL_DISK_FM7_XANADU2_D;
618 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 8 && t[3] == 1) {
620 static const uint8_t xanadu1fm_d_1[] = {
621 0xFF, 0x43, 0x6F, 0x6E, 0x74, 0x69, 0x6E, 0x75,
622 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70,
623 0x72, 0x6F, 0x67, 0x72, 0x61 ,0x6D, 0x2E, 0x0D,
624 0xFF, 0x00, 0x34, 0x01, 0x1C ,0xAF, 0x6F, 0x8D,
625 0x01, 0x3F, 0x17, 0xFA, 0xE4, 0x27, 0xFB, 0x35,
626 0x81, 0x34, 0x13, 0xA6, 0x80, 0x81, 0xFF, 0x27,
627 0x04, 0x8D, 0x04, 0x20, 0xF6, 0x35, 0x93, 0x34,
628 0x15, 0xA7, 0x8D, 0x00, 0xB6, 0xC6, 0x05, 0x30,
629 0x8D, 0x00, 0xAC, 0x17, 0x00, 0xB6, 0x17, 0x00,
630 0xD6, 0x35, 0x95, 0x00, 0x00, 0x3F, 0x59, 0x41,
631 0x4D, 0x41, 0x55, 0x43, 0x48, 0x49, 0x91, 0xD3,
633 static const uint8_t xanadu1fm_d_2[] = {
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x3F, 0x59, 0x41, 0x4D,
637 0x41, 0x55, 0x43, 0x48, 0x49, 0x93, 0xD3, 0x8F,
640 if(memcmp((void *)(t + 0x10 + 0), xanadu1fm_d_1, sizeof(xanadu1fm_d_1)) == 0) {
641 if(memcmp((void *)(t + 0x10 + 0xb0), xanadu1fm_d_2, sizeof(xanadu1fm_d_2)) == 0) {
642 is_special_disk = SPECIAL_DISK_FM7_XANADU2_D; // Same issue as Xanadu2.
646 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 1 && t[3] == 1) {
647 //$03 + $2D + "PSY-O-BLADE Copyright 1988 by T&E SOFT Inc." + $B6 + $FD + $05
648 static const uint8_t psyoblade_ipl1[] ={
649 0x03, 0x2d, 0x50, 0x53, 0x59, 0xa5, 0x4f, 0xa5,
650 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20, 0x20, 0x20,
651 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
652 0x74, 0x20, 0x31, 0x39, 0x38, 0x38, 0x20, 0x62,
653 0x79, 0x20, 0x54, 0x26, 0x45, 0x20, 0x53, 0x4f,
654 0x46, 0x54, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0xb6,
658 static const uint8_t psyoblade_disk_1[] ={
659 0xc3, 0x00, 0x01, 0x00, 0x1a, 0x50, 0x86, 0xff,
660 0xb7, 0xfd, 0x10, 0xb7, 0xfd, 0x0f, 0x30, 0x8c,
661 0x0e, 0x8d, 0x35, 0x30, 0x8c, 0x14, 0x8d, 0x30,
662 0x30, 0x8c, 0x14, 0x8d, 0x2b, 0x20, 0xfe, 0x0a,
664 //$00 + $00 + $03 + $14 + "PSY-O-BLADE DISK" + $B6 + $FD + $05
665 static const uint8_t psyoblade_disk_2[] ={
666 0x00, 0x00, 0x03, 0x14, 0x50, 0x53, 0x59, 0xa5,
667 0x4f, 0xa5, 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20,
668 0x20, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20
670 //RIGLAS/FM: $3E - $7D
671 static const uint8_t riglas_fm[] = {
672 0x0d, 0x56, /* $3e-$3f */
673 0x44, 0x53, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, /* $40-$47 */
674 0x43, 0x4d, 0x44, 0x00, 0x00, 0x02, 0x1b, 0x02, /* $48-$4f */
675 0x1e, 0x00, 0x04, 0x00, 0x00, 0x03, 0x0d, 0x56, /* $50-$57 */
676 0x43, 0x4f, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00, /* $58-$5f */
677 0x43, 0x4d, 0x44, 0x00, 0x00, 0x02, 0x1f, 0x03, /* $60-$67 */
678 0x03, 0x00, 0x05, 0x00, 0x00, 0x03, 0x0d, 0x56, /* $68-$6f */
679 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x00, 0x00, /* $70-$77 */
680 0x43, 0x4d, 0x44, 0x00, 0x00, 0x03 /* $78-$7d */
682 if(memcmp((void *)(t + 0x58), psyoblade_ipl1, sizeof(psyoblade_ipl1)) == 0) {
683 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
685 } else if(memcmp((void *)(t + 0x10), psyoblade_disk_1, sizeof(psyoblade_disk_1)) == 0) {
686 if(memcmp((void *)(t + 0x40), psyoblade_disk_2, sizeof(psyoblade_disk_2)) == 0) {
687 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
690 } else if(memcmp((void *)(t + 0x3e + 0x10), riglas_fm, sizeof(riglas_fm)) == 0) {
691 is_special_disk = SPECIAL_DISK_FM7_RIGLAS;
694 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 3 && t[3] == 1) {
695 static const uint8_t taiyoufm1[] = {
696 0x10, 0xff, 0x04, 0x9f, 0x10, 0xce, 0xfc, 0xf4,
697 0x37, 0x20, 0x34, 0x20, 0x37, 0x36, 0x34, 0x36, //7 4 7646
698 0x37, 0x36, 0x34, 0x36, 0x37, 0x36, 0x34, 0x36, //76467646
699 0x37, 0x36, 0x34, 0x36, 0x37, 0x36, 0x34, 0x36, //76467646
700 0x37, 0x36, 0x34, 0x36, 0x37, 0x36, 0x34, 0x36, //76467646
701 0x37, 0x36, 0x34, 0x36, 0x37, 0x36, 0x34, 0x36, //76467646
702 0x37, 0x36, 0x34, 0x36, 0x37, 0x36, 0x34, 0x36, //76467646
703 0x10, 0xfe, 0x04, 0x9f, 0x1c, 0xef, 0x86, 0xff,
704 0xb7, 0xfc, 0xf8, 0x17, 0x03, 0x3d, 0x33, 0xc9,
705 0xdb, 0x9c, 0x35, 0x04, 0x5a, 0x26, 0xa0, 0xfe,
707 if(memcmp((void *)(t + 0x70), taiyoufm1, sizeof(taiyoufm1)) == 0) {
708 is_special_disk = SPECIAL_DISK_FM7_TAIYOU1;
711 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 2 && t[3] == 1) {
712 static const uint8_t taiyoufm2[] = {
713 0x3d, 0x02, 0xa3, 0xd6, 0x01, 0xc7, 0x06, 0x86,
714 0x07, 0x00, 0x00, 0xc7, 0x06, 0xd4, 0x01, 0x00,
715 0x00, 0xb4, 0x19, 0xcd, 0x21, 0xfe, 0xc0, 0xa2,
716 0xda, 0x01, 0x06, 0xb9, 0x10, 0x00, 0xbb, 0x40,
717 0x00, 0x8e, 0xc3, 0xbb, 0x00, 0x00, 0xfe, 0x06,
718 0xd9, 0x01, 0x26, 0x80, 0xbf, 0x6c, 0x02, 0x00,
719 0x74, 0x03, 0x43, 0xe2, 0xf1, 0x07, 0xc6, 0x06,
720 0xdb, 0x01, 0x00, 0xbb, 0x80, 0x00, 0x80, 0x3f,
722 if(memcmp((void *)(t + 0x00), taiyoufm2, sizeof(taiyoufm2)) == 0) {
723 is_special_disk = SPECIAL_DISK_FM7_TAIYOU2;
727 t += data_size.sd + 0x10;
732 //#elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
733 // FIXME: ugly patch for X1turbo ALPHA and X1 Batten Tanuki
734 if(media_type == MEDIA_TYPE_2D) {
737 offset.read_4bytes_le_from(buffer + 0x20);
738 if(IS_VALID_TRACK(offset.d)) {
739 // check first sector
740 static const uint8_t batten[] = {0xca, 0xde, 0xaf, 0xc3, 0xdd, 0x20, 0xc0, 0xc7, 0xb7};
741 uint8_t *t = buffer + offset.d;
742 //#if defined(_X1TURBO) || defined(_X1TURBOZ)
743 // if(strncmp((char *)(t + 0x11), "turbo ALPHA", 11) == 0) {
744 // is_special_disk = SPECIAL_DISK_X1TURBO_ALPHA;
747 if(memcmp((void *)(t + 0x11), batten, sizeof(batten)) == 0) {
748 is_special_disk = SPECIAL_DISK_X1_BATTEN;
763 trim_required = false;
765 buffer[0x1a] = write_protected ? 0x10 : 0; // mey be changed
767 if(/*!write_protected &&*/ !(file_size.d == orig_file_size && get_crc32(buffer, file_size.d) == orig_crc32)) {
769 FILEIO* fio = new FILEIO();
770 int pre_size = 0, post_size = 0;
771 uint8_t *pre_buffer = NULL, *post_buffer = NULL;
773 // is this d88 format ?
774 if(check_file_extension(dest_path, _T(".d88")) || check_file_extension(dest_path, _T(".d77")) || check_file_extension(dest_path, _T(".1dd"))) {
775 if(fio->Fopen(dest_path, FILEIO_READ_BINARY)) {
776 fio->Fseek(0, FILEIO_SEEK_END);
777 uint32_t total_size = fio->Ftell(), offset = 0;
778 for(int i = 0; i < file_bank; i++) {
779 fio->Fseek(offset + 0x1c, SEEK_SET);
780 offset += fio->FgetUint32_LE();
782 if((pre_size = offset) > 0) {
783 pre_buffer = (uint8_t *)malloc(pre_size);
784 fio->Fseek(0, FILEIO_SEEK_SET);
785 fio->Fread(pre_buffer, pre_size, 1);
787 fio->Fseek(offset + 0x1c, SEEK_SET);
788 offset += fio->FgetUint32_LE();
789 if((post_size = total_size - offset) > 0) {
790 post_buffer = (uint8_t *)malloc(post_size);
791 fio->Fseek(offset, FILEIO_SEEK_SET);
792 fio->Fread(post_buffer, post_size, 1);
798 // is this solid image and was physical formatted ?
800 bool formatted = false;
803 for(int trkside = 0; trkside < 164; trkside++) {
805 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
807 if(!IS_VALID_TRACK(offset.d)) {
810 if(solid_nside == 1 && (trkside & 1) == 1) {
815 uint8_t* t = buffer + offset.d;
816 pair_t sector_num, data_size;
817 sector_num.read_2bytes_le_from(t + 4);
819 if(sector_num.sd != solid_nsec) {
822 for(int i = 0; i < sector_num.sd; i++) {
823 data_size.read_2bytes_le_from(t + 14);
824 if(data_size.sd != solid_size) {
827 if(t[6] != (solid_mfm ? 0 : 0x40)) {
830 t += data_size.sd + 0x10;
833 if(tracks != (solid_ncyl * solid_nside)) {
837 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), orig_path);
838 is_solid_image = false;
842 if((FILEIO::IsFileExisting(dest_path) && FILEIO::IsFileProtected(dest_path)) || !fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
843 fio->Fopen(local_path(create_string(_T("temporary_saved_floppy_disk_#%d.d88"), drive_num)), FILEIO_WRITE_BINARY);
845 if(fio->IsOpened()) {
847 fio->Fwrite(pre_buffer, pre_size, 1);
851 fio->Fwrite(fdi_header, 4096, 1);
853 for(int trkside = 0; trkside < 164; trkside++) {
855 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
857 if(!IS_VALID_TRACK(offset.d)) {
860 uint8_t* t = buffer + offset.d;
861 pair_t sector_num, data_size;
862 sector_num.read_2bytes_le_from(t + 4);
864 for(int i = 0; i < sector_num.sd; i++) {
865 data_size.read_2bytes_le_from(t + 14);
866 fio->Fwrite(t + 0x10, data_size.sd, 1);
867 t += data_size.sd + 0x10;
871 fio->Fwrite(buffer, file_size.d, 1);
874 fio->Fwrite(post_buffer, post_size, 1);
888 inserted = write_protected = false;
890 sector_size.sd = sector_num.sd = 0;
895 void DISK::save_as_d88(const _TCHAR* file_path)
899 FILEIO* fio = new FILEIO();
900 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
902 memcpy(tmp_buffer, buffer + 0x20, 4 * 82);
903 for(int trk = 0; trk < 82; trk++) {
904 memcpy(buffer + 0x20 + (trk * 2 + 0) * 4, tmp_buffer + trk * 4, 4);
905 memset(buffer + 0x20 + (trk * 2 + 1) * 4, 0, 4);
907 buffer[0x1b] = MEDIA_TYPE_2DD;
909 fio->Fwrite(buffer, file_size.d, 1);
918 bool DISK::get_track(int trk, int side)
920 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
921 if(trk >= 0) trk >>= 1;
922 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
923 if(trk >= 0) trk <<= 1;
925 return get_track_tmp(trk, side);
928 bool DISK::get_track_tmp(int trk, int side)
930 sector_size.sd = sector_num.sd = 0;
931 invalid_format = false;
934 // disk not inserted or invalid media type
935 if(!(inserted && check_media_type())) {
940 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
941 if(!(0 <= trkside && trkside < 164)) {
948 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
950 if(!IS_VALID_TRACK(offset.d)) {
955 sector = buffer + offset.d;
956 sector_num.read_2bytes_le_from(sector + 4);
958 data_size.read_2bytes_le_from(sector + 14);
960 // create each sector position in track
962 if(sector_num.sd == 0) {
963 track_mfm = drive_mfm;
966 for(int i = 0; i < sector_num.sd; i++) {
967 data_size.read_2bytes_le_from(t + 14);
968 // t[6]: 0x00 = double-density, 0x40 = single-density
973 t += data_size.sd + 0x10;
976 int sync_size = track_mfm ? 12 : 6;
977 int am_size = track_mfm ? 3 : 0;
978 int gap0_size = track_mfm ? 80 : 40;
979 int gap1_size = track_mfm ? 50 : 26;
980 int gap2_size = track_mfm ? 22 : 11;
981 int gap3_size = 0, gap4_size;
983 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
985 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
986 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
987 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
989 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
990 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
991 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
995 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
996 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
997 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
999 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
1000 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
1001 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
1005 uint8_t* t = sector;
1006 int total = 0, valid_sector_num = 0;
1008 for(int i = 0; i < sector_num.sd; i++) {
1009 data_size.read_2bytes_le_from(t + 14);
1010 sync_position[i] = total; // for invalid format case
1011 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
1012 if(data_size.sd > 0) {
1013 total += sync_size + (am_size + 1);
1014 total += data_size.sd + 2;
1017 // if(t[2] != i + 1) {
1020 t += data_size.sd + 0x10;
1022 total += sync_size + (am_size + 1); // sync in preamble
1024 if(gap3_size == 0) {
1025 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (valid_sector_num + 1);
1027 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
1029 if(gap3_size < 8 || gap4_size < 8) {
1030 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + valid_sector_num + 1);
1031 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
1033 if(gap3_size < 8 || gap4_size < 8) {
1034 gap0_size = gap1_size = gap3_size = gap4_size = 8;
1035 invalid_format = true;
1037 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
1039 if(invalid_format) {
1040 total -= sync_size + (am_size + 1);
1041 for(int i = 0; i < sector_num.sd; i++) {
1042 sync_position[i] *= get_track_size() - preamble_size - gap4_size;
1043 sync_position[i] /= total;
1047 total = preamble_size;
1048 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
1050 for(int i = 0; i < sector_num.sd; i++) {
1051 data_size.read_2bytes_le_from(t + 14);
1052 if(invalid_format) {
1053 total = preamble_size + sync_position[i];
1055 sync_position[i] = total;
1057 am1_position[i] = total;
1058 total += am_size + 1;
1059 id_position[i] = total;
1060 total += (4 + 2) + gap2_size;
1061 if(data_size.sd > 0) {
1062 total += sync_size + (am_size + 1);
1063 data_position[i] = total;
1064 total += data_size.sd + 2;
1067 data_position[i] = total; // FIXME
1069 t += data_size.sd + 0x10;
1074 bool DISK::make_track(int trk, int side)
1076 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1077 if(trk >= 0) trk >>= 1;
1078 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1079 if(trk >= 0) trk <<= 1;
1081 return make_track_tmp(trk, side);
1084 bool DISK::make_track_tmp(int trk, int side)
1086 int track_size = get_track_size();
1088 if(!get_track_tmp(trk, side)) {
1089 // create a dummy track
1090 for(int i = 0; i < track_size; i++) {
1097 int sync_size = track_mfm ? 12 : 6;
1098 int am_size = track_mfm ? 3 : 0;
1099 int gap2_size = track_mfm ? 22 : 11;
1100 uint8_t gap_data = track_mfm ? 0x4e : 0xff;
1103 memset(track, gap_data, track_size);
1104 int q = sync_position[array_length(sync_position) - 1];
1107 for(int i = 0; i < sync_size; i++) {
1111 for(int i = 0; i < am_size; i++) {
1117 uint8_t *t = sector;
1119 for(int i = 0; i < sector_num.sd; i++) {
1121 data_size.read_2bytes_le_from(t + 14);
1122 int p = sync_position[i];
1125 for(int j = 0; j < sync_size; j++) {
1126 if(p < track_size) track[p++] = 0x00;
1129 uint16_t crc = 0xffff;
1130 for(int j = 0; j < am_size; j++) {
1131 if(p < track_size) track[p++] = 0xa1;
1132 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xa1]);
1134 if(p < track_size) track[p++] = 0xfe;
1135 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xfe]);
1137 if(p < track_size) track[p++] = t[0];
1138 if(p < track_size) track[p++] = t[1];
1139 if(p < track_size) track[p++] = t[2];
1140 if(p < track_size) track[p++] = t[3];
1141 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[0]]);
1142 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[1]]);
1143 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[2]]);
1144 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[3]]);
1145 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
1146 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
1148 for(int j = 0; j < gap2_size; j++) {
1149 if(p < track_size) track[p++] = gap_data;
1152 if(data_size.sd > 0) {
1154 for(int j = 0; j < sync_size; j++) {
1155 if(p < track_size) track[p++] = 0x00;
1159 for(int j = 0; j < am_size; j++) {
1160 if(p < track_size) track[p++] = 0xa1;
1161 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xa1]);
1163 uint8_t am2 = (t[7] != 0) ? 0xf8 : 0xfb;
1164 if(p < track_size) track[p++] = am2;
1165 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ am2]);
1167 for(int j = 0; j < data_size.sd; j++) {
1168 if(p < track_size) track[p++] = t[0x10 + j];
1169 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[0x10 + j]]);
1171 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
1172 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
1174 t += data_size.sd + 0x10;
1179 bool DISK::get_sector(int trk, int side, int index)
1181 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1182 if(trk >= 0) trk >>= 1;
1183 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1184 if(trk >= 0) trk <<= 1;
1186 return get_sector_tmp(trk, side, index);
1189 bool DISK::get_sector_tmp(int trk, int side, int index)
1191 sector_size.sd = sector_num.sd = 0;
1194 // disk not inserted or invalid media type
1195 if(!(inserted && check_media_type())) {
1200 if(trk == -1 && side == -1) {
1204 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
1205 if(!(0 <= trkside && trkside < 164)) {
1209 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1211 if(!IS_VALID_TRACK(offset.d)) {
1216 uint8_t* t = buffer + offset.d;
1217 sector_num.read_2bytes_le_from(t + 4);
1219 if(index >= sector_num.sd) {
1224 for(int i = 0; i < index; i++) {
1226 data_size.read_2bytes_le_from(t + 14);
1227 t += data_size.sd + 0x10;
1233 void DISK::set_sector_info(uint8_t *t)
1236 int am_size = track_mfm ? 3 : 0;
1237 uint16_t crc = 0xffff;
1238 for(int i = 0; i < am_size; i++) {
1239 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xa1]);
1241 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xfe]);
1246 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[0]]);
1247 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[1]]);
1248 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[2]]);
1249 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[3]]);
1250 id[4] = (crc >> 8) & 0xff;
1251 id[5] = (crc >> 0) & 0xff;
1252 // http://www.gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
1253 // t[6]: 0x00 = double-density, 0x40 = single-density
1254 // t[7]: 0x00 = normal, 0x10 = deleted mark
1255 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
1257 deleted = (t[7] != 0);
1258 // if(ignore_crc()) {
1259 // addr_crc_error = false;
1260 // data_crc_error = false;
1262 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
1263 data_crc_error = ((t[8] & 0xf0) == 0xb0);
1266 sector_size.read_2bytes_le_from(t + 14);
1269 void DISK::set_deleted(bool value)
1271 if(sector != NULL) {
1272 uint8_t *t = sector - 0x10;
1273 t[7] = value ? 0x10 : 0;
1274 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
1275 t[8] = (t[8] & 0x0f) | t[7];
1281 void DISK::set_data_crc_error(bool value)
1283 if(sector != NULL) {
1284 uint8_t *t = sector - 0x10;
1285 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
1287 data_crc_error = value;
1290 void DISK::set_data_mark_missing()
1292 if(sector != NULL) {
1293 uint8_t *t = sector - 0x10;
1294 t[8] = (t[8] & 0x0f) | 0xf0;
1297 // addr_crc_error = false;
1298 data_crc_error = false;
1301 bool DISK::format_track(int trk, int side)
1303 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1304 if(trk >= 0) trk >>= 1;
1305 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1306 if(trk >= 0) trk <<= 1;
1308 return format_track_tmp(trk, side);
1311 bool DISK::format_track_tmp(int trk, int side)
1313 // disk not inserted or invalid media type
1314 if(!(inserted && check_media_type())) {
1319 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
1320 if(!(0 <= trkside && trkside < 164)) {
1324 // create new empty track
1327 trim_required = false;
1329 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
1331 offset.d = DISK_BUFFER_SIZE;
1332 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
1334 trim_required = true;
1336 track_mfm = drive_mfm;
1341 void DISK::insert_sector(uint8_t c, uint8_t h, uint8_t r, uint8_t n, bool deleted, bool data_crc_error, uint8_t fill_data, int length)
1343 uint8_t* t = buffer + DISK_BUFFER_SIZE;
1346 for(int i = 0; i < (sector_num.sd - 1); i++) {
1347 t[4] = sector_num.b.l;
1348 t[5] = sector_num.b.h;
1350 data_size.read_2bytes_le_from(t + 14);
1351 t += data_size.sd + 0x10;
1357 t[4] = sector_num.b.l;
1358 t[5] = sector_num.b.h;
1359 t[6] = track_mfm ? 0 : 0x40;
1360 t[7] = deleted ? 0x10 : 0;
1361 t[8] = data_crc_error ? 0xb0 : t[7];
1362 t[14] = (length >> 0) & 0xff;
1363 t[15] = (length >> 8) & 0xff;
1364 memset(t + 16, fill_data, length);
1369 void DISK::sync_buffer()
1373 trim_required = false;
1377 void DISK::trim_buffer()
1379 int max_tracks = 164;
1380 int track_limit = 164;
1381 uint32_t dest_offset = 0x2b0;
1384 memset(tmp_buffer, 0, sizeof(tmp_buffer));
1385 memcpy(tmp_buffer, buffer, 0x20);
1388 if(media_type == MEDIA_TYPE_2D) {
1391 for(int trkside = 0; trkside < 164; trkside++) {
1392 pair_t src_trk_offset;
1393 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1394 if(src_trk_offset.d != 0) {
1396 if(src_trk_offset.d < 0x2b0) {
1397 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1398 if(max_tracks > track_limit) {
1399 max_tracks = track_limit;
1403 if(src_trk_offset.d != 0x2b0) {
1404 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1405 if(max_tracks > 164) {
1406 dest_offset = 0x20 + max_tracks * 4);
1415 for(int trkside = 0; trkside < max_tracks; trkside++) {
1416 pair_t src_trk_offset;
1417 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1419 pair_t dest_trk_offset;
1420 dest_trk_offset.d = 0;
1422 if(IS_VALID_TRACK(src_trk_offset.d)) {
1423 uint8_t* t = buffer + src_trk_offset.d;
1424 pair_t sector_num, data_size;
1425 sector_num.read_2bytes_le_from(t + 4);
1426 if(sector_num.sd != 0) {
1427 dest_trk_offset.d = dest_offset;
1428 for(int i = 0; i < sector_num.sd; i++) {
1429 data_size.read_2bytes_le_from(t + 14);
1430 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
1431 dest_offset += data_size.sd + 0x10;
1432 t += data_size.sd + 0x10;
1436 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
1440 file_size.d = dest_offset;
1441 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
1443 memset(buffer, 0, sizeof(buffer));
1444 memcpy(buffer, tmp_buffer, min((unsigned int)sizeof(buffer), file_size.d));
1447 int DISK::get_max_tracks()
1449 if(drive_type != DRIVE_TYPE_UNK) {
1450 return (drive_type != DRIVE_TYPE_2D) ? 84 : 42;
1451 } else if(inserted) {
1452 return (media_type != MEDIA_TYPE_2D) ? 84 : 42;
1454 return 84; // 2DD or 2HD
1460 if(drive_rpm != 0) {
1462 } else if(inserted) {
1463 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
1465 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
1469 int DISK::get_track_size()
1471 if(track_size != 0) {
1473 } else if(inserted) {
1474 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : track_mfm ? 6250 : 3100;
1476 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
1480 double DISK::get_usec_per_track()
1482 return 1000000.0 / (get_rpm() / 60.0);
1485 double DISK::get_usec_per_bytes(int bytes)
1487 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1490 int DISK::get_bytes_per_usec(double usec)
1492 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1495 bool DISK::check_media_type()
1497 switch(drive_type) {
1499 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1500 case DRIVE_TYPE_2DD:
1501 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1502 case DRIVE_TYPE_2HD:
1503 return (media_type == MEDIA_TYPE_2HD);
1504 case DRIVE_TYPE_144:
1505 return (media_type == MEDIA_TYPE_144);
1506 case DRIVE_TYPE_UNK:
1507 return true; // always okay
1514 #define COPYBUFFER(src, size) { \
1515 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1518 memcpy(buffer + file_size.d, (src), (size)); \
1519 file_size.d += (size); \
1528 uint32_t trkptr[164];
1534 uint8_t dens, del, stat;
1539 // teledisk image decoder
1542 this teledisk image decoder is based on:
1544 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1545 LZSS coded by Haruhiko OKUMURA
1546 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1547 Edited and translated to English by Kenji RIKITAKE
1551 #define STRING_BUFFER_SIZE 4096
1552 #define LOOKAHEAD_BUFFER_SIZE 60
1554 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1555 #define TABLE_SIZE (N_CHAR * 2 - 1)
1556 #define ROOT_POSITION (TABLE_SIZE - 1)
1557 #define MAX_FREQ 0x8000
1559 static uint8_t td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1560 static uint16_t td_ptr;
1561 static uint16_t td_bufcnt, td_bufndx, td_bufpos;
1562 static uint16_t td_ibufcnt, td_ibufndx;
1563 static uint8_t td_inbuf[512];
1564 static uint16_t td_freq[TABLE_SIZE + 1];
1565 static short td_prnt[TABLE_SIZE + N_CHAR];
1566 static short td_son[TABLE_SIZE];
1567 static uint16_t td_getbuf;
1568 static uint8_t td_getlen;
1570 static const uint8_t td_d_code[256] = {
1571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1573 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1574 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1575 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1576 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1577 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1578 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1579 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1580 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1581 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1582 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1583 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1584 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1585 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1586 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1588 static const uint8_t td_d_len[256] = {
1589 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1590 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1591 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1592 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1593 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1594 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1595 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1596 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1597 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1598 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1599 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1600 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1601 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1602 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1603 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1604 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1607 static int td_next_word(FILEIO* fio)
1609 if(td_ibufndx >= td_ibufcnt) {
1610 td_ibufndx = td_ibufcnt = 0;
1611 memset(td_inbuf, 0, 512);
1612 for(int i = 0; i < 512; i++) {
1613 int d = fio->Fgetc();
1624 while(td_getlen <= 8) {
1625 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1631 static int td_get_bit(FILEIO* fio)
1633 if(td_next_word(fio) < 0) {
1636 short i = td_getbuf;
1639 return (i < 0) ? 1 : 0;
1642 static int td_get_byte(FILEIO* fio)
1644 if(td_next_word(fio) != 0) {
1647 uint16_t i = td_getbuf;
1654 static void td_start_huff()
1657 for(i = 0; i < N_CHAR; i++) {
1659 td_son[i] = i + TABLE_SIZE;
1660 td_prnt[i + TABLE_SIZE] = i;
1663 while(j <= ROOT_POSITION) {
1664 td_freq[j] = td_freq[i] + td_freq[i + 1];
1666 td_prnt[i] = td_prnt[i + 1] = j;
1669 td_freq[TABLE_SIZE] = 0xffff;
1670 td_prnt[ROOT_POSITION] = 0;
1673 static void td_reconst()
1677 for(i = 0; i < TABLE_SIZE; i++) {
1678 if(td_son[i] >= TABLE_SIZE) {
1679 td_freq[j] = (td_freq[i] + 1) / 2;
1680 td_son[j] = td_son[i];
1684 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1686 f = td_freq[j] = td_freq[i] + td_freq[k];
1687 for(k = j - 1; f < td_freq[k]; k--);
1690 memmove(&td_freq[k + 1], &td_freq[k], l);
1692 memmove(&td_son[k + 1], &td_son[k], l);
1695 for(i = 0; i < TABLE_SIZE; i++) {
1696 if((k = td_son[i]) >= TABLE_SIZE) {
1699 td_prnt[k] = td_prnt[k + 1] = i;
1704 static void td_update(int c)
1707 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1710 c = td_prnt[c + TABLE_SIZE];
1713 if(k > td_freq[l = c + 1]) {
1714 while(k > td_freq[++l]);
1716 td_freq[c] = td_freq[l];
1720 if(i < TABLE_SIZE) {
1726 if(j < TABLE_SIZE) {
1733 while((c = td_prnt[c]) != 0);
1736 static short td_decode_char(FILEIO* fio)
1739 uint16_t c = td_son[ROOT_POSITION];
1740 while(c < TABLE_SIZE) {
1741 if((ret = td_get_bit(fio)) < 0) {
1752 static short td_decode_position(FILEIO* fio)
1756 if((bit = td_get_byte(fio)) < 0) {
1760 c = (uint16_t)td_d_code[i] << 6;
1761 j = td_d_len[i] - 2;
1763 if((bit = td_get_bit(fio)) < 0) {
1768 return (c | (i & 0x3f));
1771 static void td_init_decode()
1773 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1776 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1777 td_text_buf[i] = ' ';
1779 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1782 static int td_decode(FILEIO* fio, uint8_t *buf, int len)
1786 for(count = 0; count < len;) {
1787 if(td_bufcnt == 0) {
1788 if((c = td_decode_char(fio)) < 0) {
1792 *(buf++) = (uint8_t)c;
1793 td_text_buf[td_ptr++] = (uint8_t)c;
1794 td_ptr &= (STRING_BUFFER_SIZE - 1);
1797 if((pos = td_decode_position(fio)) < 0) {
1800 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1801 td_bufcnt = c - 255 + THRESHOLD;
1805 while(td_bufndx < td_bufcnt && count < len) {
1806 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1807 *(buf++) = (uint8_t)c;
1809 td_text_buf[td_ptr++] = (uint8_t)c;
1810 td_ptr &= (STRING_BUFFER_SIZE - 1);
1813 if(td_bufndx >= td_bufcnt) {
1814 td_bufndx = td_bufcnt = 0;
1841 uint8_t nsec, trk, head;
1850 bool DISK::teledisk_to_d88(FILEIO *fio)
1857 bool temporary = false;
1859 // check teledisk header
1860 fio->Fseek(0, FILEIO_SEEK_SET);
1861 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1862 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1863 // this image is compressed
1864 // decompress to the temporary file
1865 FILEIO* fio_tmp = new FILEIO();
1866 if(!fio_tmp->Fopen(local_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1873 if((rd = td_decode(fio, obuf, 512)) > 0) {
1874 fio_tmp->Fwrite(obuf, rd, 1);
1882 // reopen the temporary file
1884 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1887 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1888 // this image is not compressed
1892 if(hdr.flag & 0x80) {
1894 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1895 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1898 // create d88 header
1902 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1903 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1904 d88_hdr.protect = 0; // non-protected
1907 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1910 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1911 fio->Fread(&trk, sizeof(td_trk_t), 1);
1912 while(trk.nsec != 0xff) {
1913 d88_hdr.trkptr[trkcnt++] = trkptr;
1914 if(hdr.sides == 1) {
1918 // read sectors in this track
1919 for(int i = 0; i < trk.nsec; i++) {
1920 uint8_t buf[2048], dst[2048];
1921 memset(buf, 0, sizeof(buf));
1922 memset(dst, 0, sizeof(dst));
1924 // read sector header
1925 fio->Fread(&sct, sizeof(td_sct_t), 1);
1927 // create d88 sector header
1928 memset(&d88_sct, 0, sizeof(d88_sct_t));
1933 d88_sct.nsec = trk.nsec;
1934 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1935 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1936 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1937 d88_sct.size = secsize[sct.n & 3];
1939 // create sector image
1940 if(sct.ctrl & 0x30) {
1941 d88_sct.stat = 0xf0; // data mark missing
1944 // read sector source
1945 int len = fio->Fgetc();
1946 len += fio->Fgetc() * 256 - 1;
1947 int flag = fio->Fgetc(), d = 0;
1948 fio->Fread(buf, len, 1);
1952 memcpy(dst, buf, len);
1953 } else if(flag == 1) {
1955 len2.read_2bytes_le_from(buf);
1960 } else if(flag == 2) {
1961 for(int s = 0; s < len;) {
1962 int type = buf[s++];
1963 int len2 = buf[s++];
1966 dst[d++] = buf[s++];
1968 } else if(type < 5) {
1974 for(int j = 0; j < n; j++) {
1978 for(int j = 0; j < n; j++) {
1983 break; // unknown type
1987 break; // unknown flag
1992 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1993 COPYBUFFER(dst, d88_sct.size);
1994 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1997 fio->Fread(&trk, sizeof(td_trk_t), 1);
1999 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
2000 d88_hdr.size = trkptr;
2001 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2004 FILEIO::RemoveFile(_T("teledisk.$$$"));
2009 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
2011 bool DISK::imagedisk_to_d88(FILEIO *fio)
2013 int size = fio->FileLength();
2014 fio->Fseek(0, FILEIO_SEEK_SET);
2015 fio->Fread(tmp_buffer, size, 1);
2017 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
2022 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
2029 // create d88 header
2033 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2034 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
2035 d88_hdr.protect = 0; // non-protected
2038 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2041 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
2046 // check track header
2047 uint8_t mode = tmp_buffer[pos++];
2048 uint8_t track = tmp_buffer[pos++];
2049 uint8_t head = tmp_buffer[pos++];
2050 uint8_t sector_count = tmp_buffer[pos++];
2051 uint8_t ssize = tmp_buffer[pos++];
2053 if(sector_count == 0) {
2059 uint32_t actual_size = ssize < 7 ? 128 << ssize : 8192;
2062 const uint8_t *snum = &tmp_buffer[pos];
2063 pos += sector_count;
2064 const uint8_t *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
2066 pos += sector_count;
2067 const uint8_t *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
2069 pos += sector_count;
2073 int trkside = track * 2 + (head & 1);
2075 if(trkcnt < trkside) {
2078 d88_hdr.trkptr[trkside] = trkptr;
2080 if(img_mode == -1) {
2081 img_mode = mode & 3;
2084 // read sectors in this track
2085 for(int i = 0; i < sector_count; i++) {
2086 // create d88 sector header
2087 uint8_t stype = tmp_buffer[pos++];
2088 memset(&d88_sct, 0, sizeof(d88_sct_t));
2089 d88_sct.c = tnum ? tnum[i] : track;
2090 d88_sct.h = hnum ? hnum[i] : head;
2091 d88_sct.r = snum[i];
2093 d88_sct.nsec = sector_count;
2094 d88_sct.dens = (mode < 3) ? 0x40 : 0;
2096 if(stype == 0 || stype > 8) {
2097 d88_sct.stat = 0xf0; // data mark missing
2100 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
2101 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
2102 d88_sct.size = actual_size;
2104 // create sector image
2105 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
2106 memset(dst, tmp_buffer[pos++], actual_size);
2108 memcpy(dst, &tmp_buffer[pos], actual_size);
2109 pos += d88_sct.size;
2115 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2116 COPYBUFFER(dst, d88_sct.size);
2117 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2121 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
2122 d88_hdr.size = trkptr;
2123 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2127 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
2129 #define DSK_FORMAT_HEADER "MV - CPC"
2130 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
2133 struct track_header {
2134 uint8_t headertag[13];
2137 uint8_t track_number;
2138 uint8_t side_number;
2141 uint8_t sector_size_code;
2142 uint8_t number_of_sector;
2143 uint8_t gap3_length;
2144 uint8_t filler_byte;
2146 struct sector_header {
2150 uint8_t sector_size_code;
2151 uint8_t fdc_status_reg1;
2152 uint8_t fdc_status_reg2;
2153 uint16_t data_length;
2157 bool DISK::cpdread_to_d88(FILEIO *fio)
2159 bool extendformat = false;
2160 int image_size = fio->FileLength();
2162 fio->Fseek(0, FILEIO_SEEK_SET);
2163 fio->Fread(tmp_buffer, image_size, 1);
2165 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
2166 extendformat = true;
2167 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
2168 extendformat = false;
2173 int heads = tmp_buffer[0x31];
2178 int tracks = tmp_buffer[0x30];
2179 int track_offsets[84 * 2];
2180 bool track_offsets_error = false;
2182 int cnt = 0, tmp = 0x100;
2183 for(int i = 0; i < tracks * heads; i++) {
2184 track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0);
2185 if(track_offsets_error) {
2188 track_offsets[cnt] = tmp;
2189 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
2193 int cnt = 0, tmp = 0x100;
2194 for(int i = 0; i < tracks * heads; i++) {
2195 int length = tmp_buffer[0x34 + i] << 8;
2197 track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0);
2198 if(track_offsets_error) {
2201 track_offsets[cnt] = tmp;
2204 track_offsets[cnt] = image_size;
2209 if(track_offsets_error) {
2210 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
2211 // so I modified this code to search "Track-Info" at the top of track information block
2212 int cnt = 0, tmp = 0x100;
2213 for(int i = 0; i < tracks * heads; i++) {
2215 for(; tmp < image_size; tmp += 0x10) {
2216 found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0);
2222 track_offsets[cnt] = tmp;
2225 track_offsets[cnt] = image_size;
2231 // create d88 header
2235 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2236 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
2237 d88_hdr.protect = 0; // non-protected
2240 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2243 int total = 0, trkptr = sizeof(d88_hdr_t);
2245 for(int track = 0; track < tracks; track++) {
2246 for(int side = 0; side < heads; side++) {
2247 if(track_offsets[(track << 1) + side] >= image_size) {
2250 if((track << 1) + side < 164) {
2251 d88_hdr.trkptr[(track << 1) + side] = trkptr;
2255 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
2256 int pos = track_offsets[(track << 1) + side] + 0x100;
2257 for(int j = 0; j < tr.number_of_sector; j++) {
2258 sector_header sector;
2259 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
2261 // create d88 sector header
2262 memset(&d88_sct, 0, sizeof(d88_sct_t));
2263 d88_sct.c = sector.track;
2264 d88_sct.h = sector.side;
2265 d88_sct.r = sector.sector_id;
2266 d88_sct.n = sector.sector_size_code;
2267 d88_sct.nsec = tr.number_of_sector;
2269 d88_sct.size = sector.data_length;
2270 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
2272 d88_sct.size = 128 << tr.sector_size_code;
2273 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
2275 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
2276 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
2279 if((track << 1) + side < 164) {
2280 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2281 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
2282 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2284 total += d88_sct.size;
2287 pos += sector.data_length;
2289 pos += 128 << tr.sector_size_code;
2294 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
2295 d88_hdr.size = trkptr;
2296 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2300 // nfd r0/r1 image decoder
2302 bool DISK::nfdr0_to_d88(FILEIO *fio)
2304 // from NFD r0
\8c`
\8e®
\83t
\83@
\83C
\83\8b\8d\
\91¢
\8ed
\97l 2001/01/22 LED
2306 BYTE C; // C
\81i0xFF
\82Ì
\8e\9e\83Z
\83N
\83^
\96³
\82µ
\81j
2310 BYTE flMFM; // 0:FM / 1:MFM
2311 BYTE flDDAM; // 0:DAM / 1:DDAM
2312 BYTE byStatus; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê
2313 BYTE byST0; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST0
2314 BYTE byST1; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST1
2315 BYTE byST2; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST2
2316 BYTE byPDA; // FDDBIOS
\82Å
\8eg
\97p
\82·
\82é
\83A
\83h
\83\8c\83X
2317 char Reserve1[5]; //
\97\
\96ñ
2318 }NFD_SECT_ID,*LP_NFD_SECT_ID;
2321 char szFileID[15]; //
\8e¯
\95ÊID "T98FDDIMAGE.R0"
2322 char Reserve1[1]; //
\97\
\96ñ
2323 char szComment[0x100]; //
\83C
\83\81\81[
\83W
\83R
\83\81\83\93\83g(ASCIIz)
2324 DWORD dwHeadSize; //
\83w
\83b
\83_
\95\94\82Ì
\83T
\83C
\83Y
2325 BYTE flProtect; // 0
\88È
\8aO :
\83\89\83C
\83g
\83v
\83\8d\83e
\83N
\83g
2326 BYTE byHead; //
\83w
\83b
\83h
\90\94
2327 char Reserve2[10]; //
\97\
\96ñ
2328 NFD_SECT_ID si[163][26]; //
\83Z
\83N
\83^ID(
\8cã
\8fq)
2329 char Reserve3[0x10]; //
\97\
\96ñ
2330 }NFD_FILE_HEAD,*LP_NFD_FILE_HEAD;
2335 fio->Fseek(0, FILEIO_SEEK_SET);
2336 fio->Fread(&head, sizeof(head), 1);
2338 if(strncmp(head.szFileID, "T98FDDIMAGE.R0", 14) != 0) {
2341 fio->Fseek(head.dwHeadSize, FILEIO_SEEK_SET);
2343 // create d88 header
2347 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2348 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "NFD R0");
2349 d88_hdr.protect = head.flProtect;
2352 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2355 int trkptr = sizeof(d88_hdr_t);
2357 for(int c = 0; c < 163; c++) {
2360 for(int s = 0; s < 26; s++) {
2361 if(head.si[c][s].C != 0xff) {
2366 d88_hdr.trkptr[c] = trkptr;
2368 // read sectors in this track
2369 for(int s = 0; s < 26; s++) {
2370 if(head.si[c][s].C != 0xff) {
2371 // create d88 sector header
2372 memset(&d88_sct, 0, sizeof(d88_sct_t));
2373 d88_sct.c = head.si[c][s].C;
2374 d88_sct.h = head.si[c][s].H;
2375 d88_sct.r = head.si[c][s].R;
2376 d88_sct.n = head.si[c][s].N;
2377 d88_sct.nsec = nsec;
2378 d88_sct.dens = head.si[c][s].flMFM ? 0 : 0x40;
2379 d88_sct.del = head.si[c][s].flDDAM ? 0x10 : 0;
2380 if(head.si[c][s].byST1 & 0x20) {
2381 if(head.si[c][s].byST2 & 0x20) {
2382 d88_sct.stat = 0xb0; // data crc error
2384 d88_sct.stat = 0xa0; // id crc error
2386 } else if(head.si[c][s].byST1 & 0x01) {
2387 d88_sct.stat = 0xe0; // address mark missing
2388 } else if(head.si[c][s].byST2 & 0x01) {
2389 d88_sct.stat = 0xf0; // data mark missing
2391 d88_sct.stat = d88_sct.del;
2393 d88_sct.size = secsize[d88_sct.n & 3];
2395 // create sector image
2397 memset(dst, 0xe5, sizeof(dst));
2398 fio->Fread(dst, d88_sct.size, 1);
2401 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2402 COPYBUFFER(dst, d88_sct.size);
2403 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2405 if(head.si[c][s].byPDA == 0x10) {
2406 d88_hdr.type = MEDIA_TYPE_2DD;
2408 d88_hdr.type = MEDIA_TYPE_2HD;
2414 d88_hdr.size = trkptr;
2415 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2419 bool DISK::nfdr1_to_d88(FILEIO *fio)
2421 // from NFD r1
\8c`
\8e®
\83t
\83@
\83C
\83\8b\8d\
\91¢
\8ed
\97l 2001/09/14 LED
2423 // char szFileID[sizeof(NFD_FILE_ID1)]; /*
\8e¯
\95ÊID "T98FDDIMAGE.R1" */
2424 // char Reserv1[0x10-sizeof(NFD_FILE_ID1)]; /*
\97\
\94õ */
2425 char szFileID[15]; /*
\8e¯
\95ÊID "T98FDDIMAGE.R1" */
2426 char Reserve1[1]; /*
\97\
\96ñ */
2427 char szComment[0x100]; /*
\83R
\83\81\83\93\83g */
2428 DWORD dwHeadSize; /*
\83w
\83b
\83_
\82Ì
\83T
\83C
\83Y */
2429 BYTE flProtect; /*
\83\89\83C
\83g
\83v
\83\8d\83e
\83N
\83g0
\88È
\8aO */
2430 BYTE byHead; /*
\83w
\83b
\83h
\90\94 1-2 */
2431 char Reserv2[0x10-4-1-1]; /*
\97\
\94õ */
2432 DWORD dwTrackHead[164]; /*
\83g
\83\89\83b
\83NID
\88Ê
\92u */
2433 DWORD dwAddInfo; /*
\92Ç
\89Á
\8fî
\95ñ
\83w
\83b
\83_
\82Ì
\83A
\83h
\83\8c\83X */
2434 char Reserv3[0x10-4]; /*
\97\
\94õ */
2435 }NFD_FILE_HEAD1,*LP_NFD_FILE_HEAD1;
2438 WORD wSector; /*
\83Z
\83N
\83^ID
\90\94 */
2439 WORD wDiag; /*
\93Á
\8eê ID
\90\94 */
2440 char Reserv1[0x10-4]; /*
\97\
\94õ */
2441 }NFD_TRACK_ID1,*LP_NFD_TRACK_ID1;
2448 BYTE flMFM; /* MFM(1)/FM(0) */
2449 BYTE flDDAM; /* DDAM(1)/DAM(0) */
2450 BYTE byStatus; /* READ DATA RESULT */
2451 BYTE bySTS0; /* ST0 */
2452 BYTE bySTS1; /* ST1 */
2453 BYTE bySTS2; /* ST2 */
2454 BYTE byRetry; /* RetryData
\82È
\82µ(0)
\82 \82è(1-) */
2455 BYTE byPDA; /* PDA */
2456 char Reserv1[0x10-12]; /*
\97\
\94õ */
2457 }NFD_SECT_ID1,*LP_NFD_SECT_ID1;
2460 BYTE Cmd; /* Command */
2465 BYTE byStatus; /* READ DATA RESULT */
2466 BYTE bySTS0; /* ST0 */
2467 BYTE bySTS1; /* ST1 */
2468 BYTE bySTS2; /* ST2 */
2469 BYTE byRetry; /* RetryData
\82È
\82µ(0)
\82 \82è(1-) */
2471 BYTE byPDA; /* PDA */
2472 char Reserv1[0x10-15]; /*
\97\
\94õ */
2473 }NFD_DIAG_ID1,*LP_NFD_DIAG_ID1;
2476 NFD_FILE_HEAD1 head;
2478 fio->Fseek(0, FILEIO_SEEK_SET);
2479 fio->Fread(&head, sizeof(head), 1);
2481 if(strncmp(head.szFileID, "T98FDDIMAGE.R1", 14) != 0) {
2484 fio->Fseek(head.dwHeadSize, FILEIO_SEEK_SET);
2486 // not implemented yet :-(
2490 // solid image decoder
2492 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
2498 solid_nside = nside;
2503 // create d88 header
2507 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2508 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
2509 d88_hdr.protect = 0; // non-protected
2512 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2515 for(int i = 0; i < 8; i++) {
2516 if(size == (128 << i)) {
2523 int trkptr = sizeof(d88_hdr_t);
2525 for(int c = 0; c < ncyl; c++) {
2526 for(int h = 0; h < nside; h++) {
2527 d88_hdr.trkptr[t++] = trkptr;
2532 // read sectors in this track
2533 for(int s = 0; s < nsec; s++) {
2534 // create d88 sector header
2535 memset(&d88_sct, 0, sizeof(d88_sct_t));
2540 d88_sct.nsec = nsec;
2544 d88_sct.size = size;
2546 // create sector image
2548 memset(dst, 0xe5, sizeof(dst));
2549 fio->Fread(dst, size, 1);
2552 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2553 COPYBUFFER(dst, size);
2554 trkptr += sizeof(d88_sct_t) + size;
2558 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
2559 d88_hdr.size = trkptr;
2560 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2564 #define STATE_VERSION 14
2566 #include "../../statesub.h"
2568 void DISK::decl_state()
2570 state_entry = new csp_state_utils(STATE_VERSION, drive_num, _T("FLOPPY_DISK"));
2572 DECL_STATE_ENTRY_1D_ARRAY(buffer, sizeof(buffer));
2573 DECL_STATE_ENTRY_STRING(orig_path, sizeof(orig_path) / sizeof(_TCHAR));
2574 DECL_STATE_ENTRY_STRING(dest_path, sizeof(dest_path) / sizeof(_TCHAR));
2576 DECL_STATE_ENTRY_PAIR(file_size);
2577 DECL_STATE_ENTRY_INT32(file_bank);
2578 DECL_STATE_ENTRY_UINT32(orig_file_size);
2579 DECL_STATE_ENTRY_UINT32(orig_crc32);
2580 DECL_STATE_ENTRY_BOOL(trim_required);
2581 DECL_STATE_ENTRY_BOOL(is_1dd_image);
2582 DECL_STATE_ENTRY_BOOL(is_solid_image);
2583 DECL_STATE_ENTRY_BOOL(is_fdi_image);
2585 DECL_STATE_ENTRY_1D_ARRAY(fdi_header, sizeof(fdi_header));
2587 DECL_STATE_ENTRY_INT32(solid_ncyl);
2588 DECL_STATE_ENTRY_INT32(solid_nside);
2589 DECL_STATE_ENTRY_INT32(solid_nsec);
2590 DECL_STATE_ENTRY_INT32(solid_size);
2591 DECL_STATE_ENTRY_BOOL(solid_mfm);
2592 DECL_STATE_ENTRY_BOOL(inserted);
2593 DECL_STATE_ENTRY_BOOL(ejected);
2594 DECL_STATE_ENTRY_BOOL(write_protected);
2595 DECL_STATE_ENTRY_BOOL(changed);
2596 DECL_STATE_ENTRY_UINT8(media_type);
2597 DECL_STATE_ENTRY_INT32(is_special_disk);
2599 DECL_STATE_ENTRY_1D_ARRAY(track, sizeof(track));
2601 DECL_STATE_ENTRY_PAIR(sector_num);
2602 DECL_STATE_ENTRY_BOOL(track_mfm);
2603 DECL_STATE_ENTRY_BOOL(invalid_format);
2604 // DECL_STATE_ENTRY_BOOL(no_skew);
2605 DECL_STATE_ENTRY_1D_ARRAY(sync_position, sizeof(sync_position) / sizeof(int));
2606 DECL_STATE_ENTRY_1D_ARRAY(am1_position, sizeof(am1_position) / sizeof(int));
2607 DECL_STATE_ENTRY_1D_ARRAY(id_position, sizeof(id_position) / sizeof(int));
2608 DECL_STATE_ENTRY_1D_ARRAY(data_position, sizeof(data_position) / sizeof(int));
2609 // DECL_STATE_ENTRY_INT32(gap3_size);
2610 DECL_STATE_ENTRY_INT32(_tmp_sector_offset);
2611 DECL_STATE_ENTRY_PAIR(sector_size);
2613 DECL_STATE_ENTRY_1D_ARRAY(id, sizeof(id));
2614 DECL_STATE_ENTRY_UINT8(density);
2615 DECL_STATE_ENTRY_BOOL(deleted);
2616 DECL_STATE_ENTRY_BOOL(addr_crc_error);
2617 DECL_STATE_ENTRY_BOOL(data_crc_error);
2618 DECL_STATE_ENTRY_UINT8(drive_type);
2619 DECL_STATE_ENTRY_INT32(drive_rpm);
2620 DECL_STATE_ENTRY_BOOL(drive_mfm);
2622 void DISK::save_state(FILEIO* state_fio)
2624 _tmp_sector_offset = (sector != NULL) ? (int)(sector - buffer) : -1;
2626 if(state_entry != NULL) {
2627 state_entry->save_state(state_fio);
2629 //state_fio->FputUint32(STATE_VERSION);
2631 //state_fio->Fwrite(buffer, sizeof(buffer), 1);
2632 //state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
2633 //state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
2634 //state_fio->FputUint32(file_size.d);
2635 //state_fio->FputInt32(file_bank);
2636 //state_fio->FputUint32(orig_file_size);
2637 //state_fio->FputUint32(orig_crc32);
2638 //state_fio->FputBool(trim_required);
2639 //state_fio->FputBool(is_1dd_image);
2640 //state_fio->FputBool(is_solid_image);
2641 //state_fio->FputBool(is_fdi_image);
2642 //state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
2643 //state_fio->FputInt32(solid_ncyl);
2644 //state_fio->FputInt32(solid_nside);
2645 //state_fio->FputInt32(solid_nsec);
2646 //state_fio->FputInt32(solid_size);
2647 //state_fio->FputBool(solid_mfm);
2648 //state_fio->FputBool(inserted);
2649 //state_fio->FputBool(ejected);
2650 //state_fio->FputBool(write_protected);
2651 //state_fio->FputBool(changed);
2652 //state_fio->FputUint8(media_type);
2653 //state_fio->FputInt32(is_special_disk);
2654 //state_fio->Fwrite(track, sizeof(track), 1);
2655 //state_fio->FputInt32(sector_num.sd);
2656 //state_fio->FputBool(track_mfm);
2657 //state_fio->FputBool(invalid_format);
2658 // state_fio->FputBool(no_skew);
2659 //state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
2660 //state_fio->Fwrite(am1_position, sizeof(am1_position), 1);
2661 //state_fio->Fwrite(id_position, sizeof(id_position), 1);
2662 //state_fio->Fwrite(data_position, sizeof(data_position), 1);
2663 // state_fio->FputInt32(gap3_size);
2664 //state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
2665 //state_fio->FputInt32(sector_size.sd);
2666 //state_fio->Fwrite(id, sizeof(id), 1);
2667 //state_fio->FputUint8(density);
2668 //state_fio->FputBool(deleted);
2669 //state_fio->FputBool(addr_crc_error);
2670 //state_fio->FputBool(data_crc_error);
2671 //state_fio->FputUint8(drive_type);
2672 //state_fio->FputInt32(drive_rpm);
2673 //state_fio->FputBool(drive_mfm);
2676 bool DISK::load_state(FILEIO* state_fio)
2679 if(state_entry != NULL) {
2680 mb = state_entry->load_state(state_fio);
2682 if(!mb) return false;
2683 //if(state_fio->FgetUint32() != STATE_VERSION) {
2686 //state_fio->Fread(buffer, sizeof(buffer), 1);
2687 //state_fio->Fread(orig_path, sizeof(orig_path), 1);
2688 //state_fio->Fread(dest_path, sizeof(dest_path), 1);
2689 //file_size.d = state_fio->FgetUint32();
2690 //file_bank = state_fio->FgetInt32();
2691 //orig_file_size = state_fio->FgetUint32();
2692 //orig_crc32 = state_fio->FgetUint32();
2693 //trim_required = state_fio->FgetBool();
2694 //is_1dd_image = state_fio->FgetBool();
2695 //is_solid_image = state_fio->FgetBool();
2696 //is_fdi_image = state_fio->FgetBool();
2697 //state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
2698 //solid_ncyl = state_fio->FgetInt32();
2699 //solid_nside = state_fio->FgetInt32();
2700 //solid_nsec = state_fio->FgetInt32();
2701 //solid_size = state_fio->FgetInt32();
2702 //solid_mfm = state_fio->FgetBool();
2703 //inserted = state_fio->FgetBool();
2704 //ejected = state_fio->FgetBool();
2705 //write_protected = state_fio->FgetBool();
2706 //changed = state_fio->FgetBool();
2707 //media_type = state_fio->FgetUint8();
2708 //is_special_disk = state_fio->FgetInt32();
2709 //state_fio->Fread(track, sizeof(track), 1);
2710 //sector_num.sd = state_fio->FgetInt32();
2711 //track_mfm = state_fio->FgetBool();
2712 //invalid_format = state_fio->FgetBool();
2713 // no_skew = state_fio->FgetBool();
2714 //state_fio->Fread(sync_position, sizeof(sync_position), 1);
2715 //state_fio->Fread(am1_position, sizeof(am1_position), 1);
2716 //state_fio->Fread(id_position, sizeof(id_position), 1);
2717 //state_fio->Fread(data_position, sizeof(data_position), 1);
2718 // gap3_size = state_fio->FgetInt32();
2719 //int offset = state_fio->FgetInt32();
2720 //sector = (offset != -1) ? buffer + offset : NULL;
2721 //sector_size.sd = state_fio->FgetInt32();
2722 //state_fio->Fread(id, sizeof(id), 1);
2723 //density = state_fio->FgetUint8();
2724 //deleted = state_fio->FgetBool();
2725 //addr_crc_error = state_fio->FgetBool();
2726 //data_crc_error = state_fio->FgetBool();
2727 //drive_type = state_fio->FgetUint8();
2728 //drive_rpm = state_fio->FgetInt32();
2729 //drive_mfm = state_fio->FgetBool();
2730 sector = (_tmp_sector_offset != -1) ? (buffer + _tmp_sector_offset) : NULL;