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 pair32_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 pair32_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 pair32_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 pair32_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 pair32_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) {
923 return false; // unformat
927 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
928 if(trk >= 0) trk <<= 1;
930 return get_track_tmp(trk, side);
933 bool DISK::get_track_tmp(int trk, int side)
935 sector_size.sd = sector_num.sd = 0;
936 invalid_format = false;
939 // disk not inserted or invalid media type
940 if(!(inserted && check_media_type())) {
945 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
946 if(!(0 <= trkside && trkside < 164)) {
953 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
955 if(!IS_VALID_TRACK(offset.d)) {
960 sector = buffer + offset.d;
961 sector_num.read_2bytes_le_from(sector + 4);
963 data_size.read_2bytes_le_from(sector + 14);
965 // create each sector position in track
967 if(sector_num.sd == 0) {
968 track_mfm = drive_mfm;
971 for(int i = 0; i < sector_num.sd; i++) {
972 data_size.read_2bytes_le_from(t + 14);
973 // t[6]: 0x00 = double-density, 0x40 = single-density
978 t += data_size.sd + 0x10;
981 int sync_size = track_mfm ? 12 : 6;
982 int am_size = track_mfm ? 3 : 0;
983 int gap0_size = track_mfm ? 80 : 40;
984 int gap1_size = track_mfm ? 50 : 26;
985 int gap2_size = track_mfm ? 22 : 11;
986 int gap3_size = 0, gap4_size;
988 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
990 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
991 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
992 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
994 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
995 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
996 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
1000 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
1001 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
1002 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
1004 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
1005 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
1006 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
1010 uint8_t* t = sector;
1011 int total = 0, valid_sector_num = 0;
1013 for(int i = 0; i < sector_num.sd; i++) {
1014 data_size.read_2bytes_le_from(t + 14);
1015 sync_position[i] = total; // for invalid format case
1016 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
1017 if(data_size.sd > 0) {
1018 total += sync_size + (am_size + 1);
1019 total += data_size.sd + 2;
1022 // if(t[2] != i + 1) {
1025 t += data_size.sd + 0x10;
1027 total += sync_size + (am_size + 1); // sync in preamble
1029 if(gap3_size == 0) {
1030 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (valid_sector_num + 1);
1032 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
1034 if(gap3_size < 8 || gap4_size < 8) {
1035 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + valid_sector_num + 1);
1036 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
1038 if(gap3_size < 8 || gap4_size < 8) {
1039 gap0_size = gap1_size = gap3_size = gap4_size = 8;
1040 invalid_format = true;
1042 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
1044 if(invalid_format) {
1045 total -= sync_size + (am_size + 1);
1046 for(int i = 0; i < sector_num.sd; i++) {
1047 sync_position[i] *= get_track_size() - preamble_size - gap4_size;
1048 sync_position[i] /= total;
1052 total = preamble_size;
1053 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
1055 for(int i = 0; i < sector_num.sd; i++) {
1056 data_size.read_2bytes_le_from(t + 14);
1057 if(invalid_format) {
1058 total = preamble_size + sync_position[i];
1060 sync_position[i] = total;
1062 am1_position[i] = total;
1063 total += am_size + 1;
1064 id_position[i] = total;
1065 total += (4 + 2) + gap2_size;
1066 if(data_size.sd > 0) {
1067 total += sync_size + (am_size + 1);
1068 data_position[i] = total;
1069 total += data_size.sd + 2;
1072 data_position[i] = total; // FIXME
1074 t += data_size.sd + 0x10;
1079 bool DISK::make_track(int trk, int side)
1081 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1084 return false; // unformat
1088 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1089 if(trk >= 0) trk <<= 1;
1091 return make_track_tmp(trk, side);
1094 bool DISK::make_track_tmp(int trk, int side)
1096 int track_size = get_track_size();
1098 if(!get_track_tmp(trk, side)) {
1099 // create a dummy track
1100 for(int i = 0; i < track_size; i++) {
1107 int sync_size = track_mfm ? 12 : 6;
1108 int am_size = track_mfm ? 3 : 0;
1109 int gap2_size = track_mfm ? 22 : 11;
1110 uint8_t gap_data = track_mfm ? 0x4e : 0xff;
1113 memset(track, gap_data, track_size);
1114 int q = sync_position[array_length(sync_position) - 1];
1117 for(int i = 0; i < sync_size; i++) {
1121 for(int i = 0; i < am_size; i++) {
1127 uint8_t *t = sector;
1129 for(int i = 0; i < sector_num.sd; i++) {
1131 data_size.read_2bytes_le_from(t + 14);
1132 int p = sync_position[i];
1135 for(int j = 0; j < sync_size; j++) {
1136 if(p < track_size) track[p++] = 0x00;
1139 uint16_t crc = 0xffff;
1140 for(int j = 0; j < am_size; j++) {
1141 if(p < track_size) track[p++] = 0xa1;
1142 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xa1]);
1144 if(p < track_size) track[p++] = 0xfe;
1145 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xfe]);
1147 if(p < track_size) track[p++] = t[0];
1148 if(p < track_size) track[p++] = t[1];
1149 if(p < track_size) track[p++] = t[2];
1150 if(p < track_size) track[p++] = t[3];
1151 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[0]]);
1152 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[1]]);
1153 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[2]]);
1154 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[3]]);
1155 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
1156 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
1158 for(int j = 0; j < gap2_size; j++) {
1159 if(p < track_size) track[p++] = gap_data;
1162 if(data_size.sd > 0) {
1164 for(int j = 0; j < sync_size; j++) {
1165 if(p < track_size) track[p++] = 0x00;
1169 for(int j = 0; j < am_size; j++) {
1170 if(p < track_size) track[p++] = 0xa1;
1171 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xa1]);
1173 uint8_t am2 = (t[7] != 0) ? 0xf8 : 0xfb;
1174 if(p < track_size) track[p++] = am2;
1175 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ am2]);
1177 for(int j = 0; j < data_size.sd; j++) {
1178 if(p < track_size) track[p++] = t[0x10 + j];
1179 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[0x10 + j]]);
1181 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
1182 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
1184 t += data_size.sd + 0x10;
1189 bool DISK::get_sector(int trk, int side, int index)
1191 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1194 return false; // unformat
1198 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1199 if(trk >= 0) trk <<= 1;
1201 return get_sector_tmp(trk, side, index);
1204 bool DISK::get_sector_tmp(int trk, int side, int index)
1206 sector_size.sd = sector_num.sd = 0;
1209 // disk not inserted or invalid media type
1210 if(!(inserted && check_media_type())) {
1215 if(trk == -1 && side == -1) {
1219 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
1220 if(!(0 <= trkside && trkside < 164)) {
1224 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1226 if(!IS_VALID_TRACK(offset.d)) {
1231 uint8_t* t = buffer + offset.d;
1232 sector_num.read_2bytes_le_from(t + 4);
1234 if(index >= sector_num.sd) {
1239 for(int i = 0; i < index; i++) {
1241 data_size.read_2bytes_le_from(t + 14);
1242 t += data_size.sd + 0x10;
1248 void DISK::set_sector_info(uint8_t *t)
1251 int am_size = track_mfm ? 3 : 0;
1252 uint16_t crc = 0xffff;
1253 for(int i = 0; i < am_size; i++) {
1254 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xa1]);
1256 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ 0xfe]);
1261 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[0]]);
1262 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[1]]);
1263 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[2]]);
1264 crc = (uint16_t)((crc << 8) ^ crc_table[(uint8_t)(crc >> 8) ^ t[3]]);
1265 id[4] = (crc >> 8) & 0xff;
1266 id[5] = (crc >> 0) & 0xff;
1269 // http://www.gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
1270 // t[6]: 0x00 = double-density, 0x40 = single-density
1271 // t[7]: 0x00 = normal, 0x10 = deleted mark
1272 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
1274 deleted = (t[7] != 0);
1275 // if(ignore_crc()) {
1276 // addr_crc_error = false;
1277 // data_crc_error = false;
1279 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
1280 data_crc_error = ((t[8] & 0xf0) == 0xb0);
1282 if(addr_crc_error || data_crc_error) {
1287 sector_size.read_2bytes_le_from(t + 14);
1290 bool DISK::get_sector_info(int trk, int side, int index, uint8_t *c, uint8_t *h, uint8_t *r, uint8_t *n, int *length)
1292 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1295 return false; // unformat
1299 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1300 if(trk >= 0) trk <<= 1;
1302 return get_sector_info_tmp(trk, side, index, c, h, r, n, length);
1305 bool DISK::get_sector_info_tmp(int trk, int side, int index, uint8_t *c, uint8_t *h, uint8_t *r, uint8_t *n, int *length)
1308 if(trk == -1 && side == -1) {
1312 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
1313 if(!(0 <= trkside && trkside < 164)) {
1317 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1319 if(!IS_VALID_TRACK(offset.d)) {
1324 uint8_t* t = buffer + offset.d;
1325 pair32_t num, data_size;
1326 num.read_2bytes_le_from(t + 4);
1328 if(index >= num.sd) {
1333 for(int i = 0; i < index; i++) {
1334 data_size.read_2bytes_le_from(t + 14);
1335 t += data_size.sd + 0x10;
1337 data_size.read_2bytes_le_from(t + 14);
1342 *length = data_size.sd;
1346 void DISK::set_deleted(bool value)
1348 if(sector != NULL) {
1349 uint8_t *t = sector - 0x10;
1350 t[7] = value ? 0x10 : 0;
1351 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
1352 t[8] = (t[8] & 0x0f) | t[7];
1358 void DISK::set_data_crc_error(bool value)
1360 if(sector != NULL) {
1361 uint8_t *t = sector - 0x10;
1362 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
1364 data_crc_error = value;
1367 void DISK::set_data_mark_missing()
1369 if(sector != NULL) {
1370 uint8_t *t = sector - 0x10;
1371 t[8] = (t[8] & 0x0f) | 0xf0;
1374 // addr_crc_error = false;
1375 data_crc_error = false;
1378 bool DISK::format_track(int trk, int side)
1380 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1383 return false; // unformat
1387 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1388 if(trk >= 0) trk <<= 1;
1390 return format_track_tmp(trk, side);
1393 bool DISK::format_track_tmp(int trk, int side)
1395 // disk not inserted or invalid media type
1396 if(!(inserted && check_media_type())) {
1401 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
1402 if(!(0 <= trkside && trkside < 164)) {
1406 // create new empty track
1409 trim_required = false;
1411 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
1413 offset.d = DISK_BUFFER_SIZE;
1414 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
1416 trim_required = true;
1418 track_mfm = drive_mfm;
1423 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)
1425 uint8_t* t = buffer + DISK_BUFFER_SIZE;
1428 for(int i = 0; i < (sector_num.sd - 1); i++) {
1429 t[4] = sector_num.b.l;
1430 t[5] = sector_num.b.h;
1432 data_size.read_2bytes_le_from(t + 14);
1433 t += data_size.sd + 0x10;
1439 t[4] = sector_num.b.l;
1440 t[5] = sector_num.b.h;
1441 t[6] = track_mfm ? 0 : 0x40;
1442 t[7] = deleted ? 0x10 : 0;
1443 t[8] = data_crc_error ? 0xb0 : t[7];
1444 t[14] = (length >> 0) & 0xff;
1445 t[15] = (length >> 8) & 0xff;
1446 memset(t + 16, fill_data, length);
1451 void DISK::sync_buffer()
1455 trim_required = false;
1459 void DISK::trim_buffer()
1461 int max_tracks = 164;
1462 int track_limit = 164;
1463 uint32_t dest_offset = 0x2b0;
1466 memset(tmp_buffer, 0, sizeof(tmp_buffer));
1467 memcpy(tmp_buffer, buffer, 0x20);
1470 if(media_type == MEDIA_TYPE_2D) {
1473 for(int trkside = 0; trkside < 164; trkside++) {
1474 pair32_t src_trk_offset;
1475 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1476 if(src_trk_offset.d != 0) {
1478 if(src_trk_offset.d < 0x2b0) {
1479 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1480 if(max_tracks > track_limit) {
1481 max_tracks = track_limit;
1485 if(src_trk_offset.d != 0x2b0) {
1486 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1487 if(max_tracks > 164) {
1488 dest_offset = 0x20 + max_tracks * 4);
1497 for(int trkside = 0; trkside < max_tracks; trkside++) {
1498 pair32_t src_trk_offset;
1499 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1501 pair32_t dest_trk_offset;
1502 dest_trk_offset.d = 0;
1504 if(IS_VALID_TRACK(src_trk_offset.d)) {
1505 uint8_t* t = buffer + src_trk_offset.d;
1506 pair32_t sector_num, data_size;
1507 sector_num.read_2bytes_le_from(t + 4);
1508 if(sector_num.sd != 0) {
1509 dest_trk_offset.d = dest_offset;
1510 for(int i = 0; i < sector_num.sd; i++) {
1511 data_size.read_2bytes_le_from(t + 14);
1512 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
1513 dest_offset += data_size.sd + 0x10;
1514 t += data_size.sd + 0x10;
1518 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
1522 file_size.d = dest_offset;
1523 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
1525 memset(buffer, 0, sizeof(buffer));
1526 memcpy(buffer, tmp_buffer, min((unsigned int)sizeof(buffer), file_size.d));
1529 int DISK::get_max_tracks()
1531 if(drive_type != DRIVE_TYPE_UNK) {
1532 return (drive_type != DRIVE_TYPE_2D) ? 84 : 42;
1533 } else if(inserted) {
1534 return (media_type != MEDIA_TYPE_2D) ? 84 : 42;
1536 return 84; // 2DD or 2HD
1542 if(drive_rpm != 0) {
1544 } else if(inserted) {
1545 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
1547 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
1551 int DISK::get_track_size()
1553 if(track_size != 0) {
1555 } else if(inserted) {
1556 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : track_mfm ? 6250 : 3100;
1558 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
1562 double DISK::get_usec_per_track()
1564 return 1000000.0 / (get_rpm() / 60.0);
1567 double DISK::get_usec_per_bytes(int bytes)
1569 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1572 int DISK::get_bytes_per_usec(double usec)
1574 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1577 bool DISK::check_media_type()
1579 switch(drive_type) {
1581 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1582 case DRIVE_TYPE_2DD:
1583 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1584 case DRIVE_TYPE_2HD:
1585 return (media_type == MEDIA_TYPE_2HD);
1586 case DRIVE_TYPE_144:
1587 return (media_type == MEDIA_TYPE_144);
1588 case DRIVE_TYPE_UNK:
1589 return true; // always okay
1596 #define COPYBUFFER(src, size) { \
1597 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1600 memcpy(buffer + file_size.d, (src), (size)); \
1601 file_size.d += (size); \
1610 uint32_t trkptr[164];
1616 uint8_t dens, del, stat;
1621 // teledisk image decoder
1624 this teledisk image decoder is based on:
1626 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1627 LZSS coded by Haruhiko OKUMURA
1628 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1629 Edited and translated to English by Kenji RIKITAKE
1633 #define STRING_BUFFER_SIZE 4096
1634 #define LOOKAHEAD_BUFFER_SIZE 60
1636 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1637 #define TABLE_SIZE (N_CHAR * 2 - 1)
1638 #define ROOT_POSITION (TABLE_SIZE - 1)
1639 #define MAX_FREQ 0x8000
1641 static uint8_t td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1642 static uint16_t td_ptr;
1643 static uint16_t td_bufcnt, td_bufndx, td_bufpos;
1644 static uint16_t td_ibufcnt, td_ibufndx;
1645 static uint8_t td_inbuf[512];
1646 static uint16_t td_freq[TABLE_SIZE + 1];
1647 static short td_prnt[TABLE_SIZE + N_CHAR];
1648 static short td_son[TABLE_SIZE];
1649 static uint16_t td_getbuf;
1650 static uint8_t td_getlen;
1652 static const uint8_t td_d_code[256] = {
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1655 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1656 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1657 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1658 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1659 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1660 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1661 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1662 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1663 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1664 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1665 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1666 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1667 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1668 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1670 static const uint8_t td_d_len[256] = {
1671 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1672 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1673 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1674 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1675 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1676 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1677 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1678 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1679 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1680 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1681 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1682 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1683 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1684 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1685 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1686 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1689 static int td_next_word(FILEIO* fio)
1691 if(td_ibufndx >= td_ibufcnt) {
1692 td_ibufndx = td_ibufcnt = 0;
1693 memset(td_inbuf, 0, 512);
1694 for(int i = 0; i < 512; i++) {
1695 int d = fio->Fgetc();
1706 while(td_getlen <= 8) {
1707 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1713 static int td_get_bit(FILEIO* fio)
1715 if(td_next_word(fio) < 0) {
1718 short i = td_getbuf;
1721 return (i < 0) ? 1 : 0;
1724 static int td_get_byte(FILEIO* fio)
1726 if(td_next_word(fio) != 0) {
1729 uint16_t i = td_getbuf;
1736 static void td_start_huff()
1739 for(i = 0; i < N_CHAR; i++) {
1741 td_son[i] = i + TABLE_SIZE;
1742 td_prnt[i + TABLE_SIZE] = i;
1745 while(j <= ROOT_POSITION) {
1746 td_freq[j] = td_freq[i] + td_freq[i + 1];
1748 td_prnt[i] = td_prnt[i + 1] = j;
1751 td_freq[TABLE_SIZE] = 0xffff;
1752 td_prnt[ROOT_POSITION] = 0;
1755 static void td_reconst()
1759 for(i = 0; i < TABLE_SIZE; i++) {
1760 if(td_son[i] >= TABLE_SIZE) {
1761 td_freq[j] = (td_freq[i] + 1) / 2;
1762 td_son[j] = td_son[i];
1766 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1768 f = td_freq[j] = td_freq[i] + td_freq[k];
1769 for(k = j - 1; f < td_freq[k]; k--);
1772 memmove(&td_freq[k + 1], &td_freq[k], l);
1774 memmove(&td_son[k + 1], &td_son[k], l);
1777 for(i = 0; i < TABLE_SIZE; i++) {
1778 if((k = td_son[i]) >= TABLE_SIZE) {
1781 td_prnt[k] = td_prnt[k + 1] = i;
1786 static void td_update(int c)
1789 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1792 c = td_prnt[c + TABLE_SIZE];
1795 if(k > td_freq[l = c + 1]) {
1796 while(k > td_freq[++l]);
1798 td_freq[c] = td_freq[l];
1802 if(i < TABLE_SIZE) {
1808 if(j < TABLE_SIZE) {
1815 while((c = td_prnt[c]) != 0);
1818 static short td_decode_char(FILEIO* fio)
1821 uint16_t c = td_son[ROOT_POSITION];
1822 while(c < TABLE_SIZE) {
1823 if((ret = td_get_bit(fio)) < 0) {
1834 static short td_decode_position(FILEIO* fio)
1838 if((bit = td_get_byte(fio)) < 0) {
1842 c = (uint16_t)td_d_code[i] << 6;
1843 j = td_d_len[i] - 2;
1845 if((bit = td_get_bit(fio)) < 0) {
1850 return (c | (i & 0x3f));
1853 static void td_init_decode()
1855 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1858 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1859 td_text_buf[i] = ' ';
1861 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1864 static int td_decode(FILEIO* fio, uint8_t *buf, int len)
1868 for(count = 0; count < len;) {
1869 if(td_bufcnt == 0) {
1870 if((c = td_decode_char(fio)) < 0) {
1874 *(buf++) = (uint8_t)c;
1875 td_text_buf[td_ptr++] = (uint8_t)c;
1876 td_ptr &= (STRING_BUFFER_SIZE - 1);
1879 if((pos = td_decode_position(fio)) < 0) {
1882 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1883 td_bufcnt = c - 255 + THRESHOLD;
1887 while(td_bufndx < td_bufcnt && count < len) {
1888 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1889 *(buf++) = (uint8_t)c;
1891 td_text_buf[td_ptr++] = (uint8_t)c;
1892 td_ptr &= (STRING_BUFFER_SIZE - 1);
1895 if(td_bufndx >= td_bufcnt) {
1896 td_bufndx = td_bufcnt = 0;
1923 uint8_t nsec, trk, head;
1932 bool DISK::teledisk_to_d88(FILEIO *fio)
1939 bool temporary = false;
1941 // check teledisk header
1942 fio->Fseek(0, FILEIO_SEEK_SET);
1943 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1944 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1945 // this image is compressed
1946 // decompress to the temporary file
1947 FILEIO* fio_tmp = new FILEIO();
1948 if(!fio_tmp->Fopen(local_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1955 if((rd = td_decode(fio, obuf, 512)) > 0) {
1956 fio_tmp->Fwrite(obuf, rd, 1);
1964 // reopen the temporary file
1966 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1969 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1970 // this image is not compressed
1974 if(hdr.flag & 0x80) {
1976 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1977 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1980 // create d88 header
1984 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1985 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1986 d88_hdr.protect = 0; // non-protected
1989 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1992 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1993 fio->Fread(&trk, sizeof(td_trk_t), 1);
1994 while(trk.nsec != 0xff) {
1995 d88_hdr.trkptr[trkcnt++] = trkptr;
1996 if(hdr.sides == 1) {
2000 // read sectors in this track
2001 for(int i = 0; i < trk.nsec; i++) {
2002 uint8_t buf[2048], dst[2048];
2003 memset(buf, 0, sizeof(buf));
2004 memset(dst, 0, sizeof(dst));
2006 // read sector header
2007 fio->Fread(&sct, sizeof(td_sct_t), 1);
2009 // create d88 sector header
2010 memset(&d88_sct, 0, sizeof(d88_sct_t));
2015 d88_sct.nsec = trk.nsec;
2016 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
2017 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
2018 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
2019 d88_sct.size = secsize[sct.n & 3];
2021 // create sector image
2022 if(sct.ctrl & 0x30) {
2023 d88_sct.stat = 0xf0; // data mark missing
2026 // read sector source
2027 int len = fio->Fgetc();
2028 len += fio->Fgetc() * 256 - 1;
2029 int flag = fio->Fgetc(), d = 0;
2030 fio->Fread(buf, len, 1);
2034 memcpy(dst, buf, len);
2035 } else if(flag == 1) {
2037 len2.read_2bytes_le_from(buf);
2042 } else if(flag == 2) {
2043 for(int s = 0; s < len;) {
2044 int type = buf[s++];
2045 int len2 = buf[s++];
2048 dst[d++] = buf[s++];
2050 } else if(type < 5) {
2056 for(int j = 0; j < n; j++) {
2060 for(int j = 0; j < n; j++) {
2065 break; // unknown type
2069 break; // unknown flag
2074 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2075 COPYBUFFER(dst, d88_sct.size);
2076 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2079 fio->Fread(&trk, sizeof(td_trk_t), 1);
2081 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
2082 d88_hdr.size = trkptr;
2083 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2086 FILEIO::RemoveFile(_T("teledisk.$$$"));
2091 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
2093 bool DISK::imagedisk_to_d88(FILEIO *fio)
2095 int size = fio->FileLength();
2096 fio->Fseek(0, FILEIO_SEEK_SET);
2097 fio->Fread(tmp_buffer, size, 1);
2099 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
2104 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
2111 // create d88 header
2115 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2116 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
2117 d88_hdr.protect = 0; // non-protected
2120 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2123 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
2128 // check track header
2129 uint8_t mode = tmp_buffer[pos++];
2130 uint8_t track = tmp_buffer[pos++];
2131 uint8_t head = tmp_buffer[pos++];
2132 uint8_t sector_count = tmp_buffer[pos++];
2133 uint8_t ssize = tmp_buffer[pos++];
2135 if(sector_count == 0) {
2141 uint32_t actual_size = ssize < 7 ? 128 << ssize : 8192;
2144 const uint8_t *snum = &tmp_buffer[pos];
2145 pos += sector_count;
2146 const uint8_t *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
2148 pos += sector_count;
2149 const uint8_t *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
2151 pos += sector_count;
2155 int trkside = track * 2 + (head & 1);
2157 if(trkcnt < trkside) {
2160 d88_hdr.trkptr[trkside] = trkptr;
2162 if(img_mode == -1) {
2163 img_mode = mode & 3;
2166 // read sectors in this track
2167 for(int i = 0; i < sector_count; i++) {
2168 // create d88 sector header
2169 uint8_t stype = tmp_buffer[pos++];
2170 memset(&d88_sct, 0, sizeof(d88_sct_t));
2171 d88_sct.c = tnum ? tnum[i] : track;
2172 d88_sct.h = hnum ? hnum[i] : head;
2173 d88_sct.r = snum[i];
2175 d88_sct.nsec = sector_count;
2176 d88_sct.dens = (mode < 3) ? 0x40 : 0;
2178 if(stype == 0 || stype > 8) {
2179 d88_sct.stat = 0xf0; // data mark missing
2182 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
2183 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
2184 d88_sct.size = actual_size;
2186 // create sector image
2187 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
2188 memset(dst, tmp_buffer[pos++], actual_size);
2190 memcpy(dst, &tmp_buffer[pos], actual_size);
2191 pos += d88_sct.size;
2197 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2198 COPYBUFFER(dst, d88_sct.size);
2199 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2203 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
2204 d88_hdr.size = trkptr;
2205 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2209 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
2211 #define DSK_FORMAT_HEADER "MV - CPC"
2212 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
2215 struct track_header {
2216 uint8_t headertag[13];
2219 uint8_t track_number;
2220 uint8_t side_number;
2223 uint8_t sector_size_code;
2224 uint8_t number_of_sector;
2225 uint8_t gap3_length;
2226 uint8_t filler_byte;
2228 struct sector_header {
2232 uint8_t sector_size_code;
2233 uint8_t fdc_status_reg1;
2234 uint8_t fdc_status_reg2;
2235 uint16_t data_length;
2239 bool DISK::cpdread_to_d88(FILEIO *fio)
2241 bool extendformat = false;
2242 int image_size = fio->FileLength();
2244 fio->Fseek(0, FILEIO_SEEK_SET);
2245 fio->Fread(tmp_buffer, image_size, 1);
2247 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
2248 extendformat = true;
2249 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
2250 extendformat = false;
2255 int heads = tmp_buffer[0x31];
2260 int tracks = tmp_buffer[0x30];
2261 int track_offsets[84 * 2];
2262 bool track_offsets_error = false;
2264 int cnt = 0, tmp = 0x100;
2265 for(int i = 0; i < tracks * heads; i++) {
2266 track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0);
2267 if(track_offsets_error) {
2270 track_offsets[cnt] = tmp;
2271 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
2275 int cnt = 0, tmp = 0x100;
2276 for(int i = 0; i < tracks * heads; i++) {
2277 int length = tmp_buffer[0x34 + i] << 8;
2279 track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0);
2280 if(track_offsets_error) {
2283 track_offsets[cnt] = tmp;
2286 track_offsets[cnt] = image_size;
2291 if(track_offsets_error) {
2292 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
2293 // so I modified this code to search "Track-Info" at the top of track information block
2294 int cnt = 0, tmp = 0x100;
2295 for(int i = 0; i < tracks * heads; i++) {
2297 for(; tmp < image_size; tmp += 0x10) {
2298 found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0);
2304 track_offsets[cnt] = tmp;
2307 track_offsets[cnt] = image_size;
2313 // create d88 header
2317 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2318 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
2319 d88_hdr.protect = 0; // non-protected
2322 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2325 int total = 0, trkptr = sizeof(d88_hdr_t);
2327 for(int track = 0; track < tracks; track++) {
2328 for(int side = 0; side < heads; side++) {
2329 if(track_offsets[(track << 1) + side] >= image_size) {
2332 if((track << 1) + side < 164) {
2333 d88_hdr.trkptr[(track << 1) + side] = trkptr;
2337 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
2338 int pos = track_offsets[(track << 1) + side] + 0x100;
2339 for(int j = 0; j < tr.number_of_sector; j++) {
2340 sector_header sector;
2341 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
2343 // create d88 sector header
2344 memset(&d88_sct, 0, sizeof(d88_sct_t));
2345 d88_sct.c = sector.track;
2346 d88_sct.h = sector.side;
2347 d88_sct.r = sector.sector_id;
2348 d88_sct.n = sector.sector_size_code;
2349 d88_sct.nsec = tr.number_of_sector;
2351 d88_sct.size = sector.data_length;
2352 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
2354 d88_sct.size = 128 << tr.sector_size_code;
2355 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
2357 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
2358 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
2361 if((track << 1) + side < 164) {
2362 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2363 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
2364 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2366 total += d88_sct.size;
2369 pos += sector.data_length;
2371 pos += 128 << tr.sector_size_code;
2376 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
2377 d88_hdr.size = trkptr;
2378 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2382 // nfd r0/r1 image decoder
2384 bool DISK::nfdr0_to_d88(FILEIO *fio)
2386 // from NFD r0
\8c`
\8e®
\83t
\83@
\83C
\83\8b\8d\
\91¢
\8ed
\97l 2001/01/22 LED
2388 BYTE C; // C
\81i0xFF
\82Ì
\8e\9e\83Z
\83N
\83^
\96³
\82µ
\81j
2392 BYTE flMFM; // 0:FM / 1:MFM
2393 BYTE flDDAM; // 0:DAM / 1:DDAM
2394 BYTE byStatus; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê
2395 BYTE byST0; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST0
2396 BYTE byST1; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST1
2397 BYTE byST2; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST2
2398 BYTE byPDA; // FDDBIOS
\82Å
\8eg
\97p
\82·
\82é
\83A
\83h
\83\8c\83X
2399 char Reserve1[5]; //
\97\
\96ñ
2400 }NFD_SECT_ID,*LP_NFD_SECT_ID;
2403 char szFileID[15]; //
\8e¯
\95ÊID "T98FDDIMAGE.R0"
2404 char Reserve1[1]; //
\97\
\96ñ
2405 char szComment[0x100]; //
\83C
\83\81\81[
\83W
\83R
\83\81\83\93\83g(ASCIIz)
2406 DWORD dwHeadSize; //
\83w
\83b
\83_
\95\94\82Ì
\83T
\83C
\83Y
2407 BYTE flProtect; // 0
\88È
\8aO :
\83\89\83C
\83g
\83v
\83\8d\83e
\83N
\83g
2408 BYTE byHead; //
\83w
\83b
\83h
\90\94
2409 char Reserve2[10]; //
\97\
\96ñ
2410 NFD_SECT_ID si[163][26]; //
\83Z
\83N
\83^ID(
\8cã
\8fq)
2411 char Reserve3[0x10]; //
\97\
\96ñ
2412 }NFD_FILE_HEAD,*LP_NFD_FILE_HEAD;
2417 fio->Fseek(0, FILEIO_SEEK_SET);
2418 fio->Fread(&head, sizeof(head), 1);
2420 if(strncmp(head.szFileID, "T98FDDIMAGE.R0", 14) != 0) {
2423 fio->Fseek(head.dwHeadSize, FILEIO_SEEK_SET);
2425 // create d88 header
2429 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2430 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "NFD R0");
2431 d88_hdr.protect = head.flProtect;
2434 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2437 int trkptr = sizeof(d88_hdr_t);
2439 for(int c = 0; c < 163; c++) {
2442 for(int s = 0; s < 26; s++) {
2443 if(head.si[c][s].C != 0xff) {
2448 d88_hdr.trkptr[c] = trkptr;
2450 // read sectors in this track
2451 for(int s = 0; s < 26; s++) {
2452 if(head.si[c][s].C != 0xff) {
2453 // create d88 sector header
2454 memset(&d88_sct, 0, sizeof(d88_sct_t));
2455 d88_sct.c = head.si[c][s].C;
2456 d88_sct.h = head.si[c][s].H;
2457 d88_sct.r = head.si[c][s].R;
2458 d88_sct.n = head.si[c][s].N;
2459 d88_sct.nsec = nsec;
2460 d88_sct.dens = head.si[c][s].flMFM ? 0 : 0x40;
2461 d88_sct.del = head.si[c][s].flDDAM ? 0x10 : 0;
2462 if(head.si[c][s].byST1 & 0x20) {
2463 if(head.si[c][s].byST2 & 0x20) {
2464 d88_sct.stat = 0xb0; // data crc error
2466 d88_sct.stat = 0xa0; // id crc error
2468 } else if(head.si[c][s].byST1 & 0x01) {
2469 d88_sct.stat = 0xe0; // address mark missing
2470 } else if(head.si[c][s].byST2 & 0x01) {
2471 d88_sct.stat = 0xf0; // data mark missing
2473 d88_sct.stat = d88_sct.del;
2475 d88_sct.size = secsize[d88_sct.n & 3];
2477 // create sector image
2479 memset(dst, 0xe5, sizeof(dst));
2480 fio->Fread(dst, d88_sct.size, 1);
2483 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2484 COPYBUFFER(dst, d88_sct.size);
2485 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2487 if(head.si[c][s].byPDA == 0x10) {
2488 d88_hdr.type = MEDIA_TYPE_2DD;
2490 d88_hdr.type = MEDIA_TYPE_2HD;
2496 d88_hdr.size = trkptr;
2497 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2501 bool DISK::nfdr1_to_d88(FILEIO *fio)
2503 // from NFD r1
\8c`
\8e®
\83t
\83@
\83C
\83\8b\8d\
\91¢
\8ed
\97l 2001/09/14 LED
2505 // char szFileID[sizeof(NFD_FILE_ID1)]; /*
\8e¯
\95ÊID "T98FDDIMAGE.R1" */
2506 // char Reserv1[0x10-sizeof(NFD_FILE_ID1)]; /*
\97\
\94õ */
2507 char szFileID[15]; /*
\8e¯
\95ÊID "T98FDDIMAGE.R1" */
2508 char Reserve1[1]; /*
\97\
\96ñ */
2509 char szComment[0x100]; /*
\83R
\83\81\83\93\83g */
2510 DWORD dwHeadSize; /*
\83w
\83b
\83_
\82Ì
\83T
\83C
\83Y */
2511 BYTE flProtect; /*
\83\89\83C
\83g
\83v
\83\8d\83e
\83N
\83g0
\88È
\8aO */
2512 BYTE byHead; /*
\83w
\83b
\83h
\90\94 1-2 */
2513 char Reserv2[0x10-4-1-1]; /*
\97\
\94õ */
2514 DWORD dwTrackHead[164]; /*
\83g
\83\89\83b
\83NID
\88Ê
\92u */
2515 DWORD dwAddInfo; /*
\92Ç
\89Á
\8fî
\95ñ
\83w
\83b
\83_
\82Ì
\83A
\83h
\83\8c\83X */
2516 char Reserv3[0x10-4]; /*
\97\
\94õ */
2517 }NFD_FILE_HEAD1,*LP_NFD_FILE_HEAD1;
2520 WORD wSector; /*
\83Z
\83N
\83^ID
\90\94 */
2521 WORD wDiag; /*
\93Á
\8eê ID
\90\94 */
2522 char Reserv1[0x10-4]; /*
\97\
\94õ */
2523 }NFD_TRACK_ID1,*LP_NFD_TRACK_ID1;
2530 BYTE flMFM; /* MFM(1)/FM(0) */
2531 BYTE flDDAM; /* DDAM(1)/DAM(0) */
2532 BYTE byStatus; /* READ DATA RESULT */
2533 BYTE bySTS0; /* ST0 */
2534 BYTE bySTS1; /* ST1 */
2535 BYTE bySTS2; /* ST2 */
2536 BYTE byRetry; /* RetryData
\82È
\82µ(0)
\82 \82è(1-) */
2537 BYTE byPDA; /* PDA */
2538 char Reserv1[0x10-12]; /*
\97\
\94õ */
2539 }NFD_SECT_ID1,*LP_NFD_SECT_ID1;
2542 BYTE Cmd; /* Command */
2547 BYTE byStatus; /* READ DATA RESULT */
2548 BYTE bySTS0; /* ST0 */
2549 BYTE bySTS1; /* ST1 */
2550 BYTE bySTS2; /* ST2 */
2551 BYTE byRetry; /* RetryData
\82È
\82µ(0)
\82 \82è(1-) */
2553 BYTE byPDA; /* PDA */
2554 char Reserv1[0x10-15]; /*
\97\
\94õ */
2555 }NFD_DIAG_ID1,*LP_NFD_DIAG_ID1;
2558 NFD_FILE_HEAD1 head;
2560 fio->Fseek(0, FILEIO_SEEK_SET);
2561 fio->Fread(&head, sizeof(head), 1);
2563 if(strncmp(head.szFileID, "T98FDDIMAGE.R1", 14) != 0) {
2566 fio->Fseek(head.dwHeadSize, FILEIO_SEEK_SET);
2568 // not implemented yet :-(
2572 // solid image decoder
2574 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
2580 solid_nside = nside;
2585 // create d88 header
2589 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2590 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
2591 d88_hdr.protect = 0; // non-protected
2594 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2597 for(int i = 0; i < 8; i++) {
2598 if(size == (128 << i)) {
2605 int trkptr = sizeof(d88_hdr_t);
2607 for(int c = 0; c < ncyl; c++) {
2608 for(int h = 0; h < nside; h++) {
2609 d88_hdr.trkptr[t++] = trkptr;
2614 // read sectors in this track
2615 for(int s = 0; s < nsec; s++) {
2616 // create d88 sector header
2617 memset(&d88_sct, 0, sizeof(d88_sct_t));
2622 d88_sct.nsec = nsec;
2626 d88_sct.size = size;
2628 // create sector image
2630 memset(dst, 0xe5, sizeof(dst));
2631 fio->Fread(dst, size, 1);
2634 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2635 COPYBUFFER(dst, size);
2636 trkptr += sizeof(d88_sct_t) + size;
2640 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
2641 d88_hdr.size = trkptr;
2642 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2646 #define STATE_VERSION 13
2648 bool DISK::process_state(FILEIO* state_fio, bool loading)
2650 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
2653 state_fio->StateArray(buffer, sizeof(buffer), 1);
2654 state_fio->StateArray(orig_path, sizeof(orig_path), 1);
2655 state_fio->StateArray(dest_path, sizeof(dest_path), 1);
2656 state_fio->StateValue(file_size.d);
2657 state_fio->StateValue(file_bank);
2658 state_fio->StateValue(orig_file_size);
2659 state_fio->StateValue(orig_crc32);
2660 state_fio->StateValue(trim_required);
2661 state_fio->StateValue(is_1dd_image);
2662 state_fio->StateValue(is_solid_image);
2663 state_fio->StateValue(is_fdi_image);
2664 state_fio->StateArray(fdi_header, sizeof(fdi_header), 1);
2665 state_fio->StateValue(solid_ncyl);
2666 state_fio->StateValue(solid_nside);
2667 state_fio->StateValue(solid_nsec);
2668 state_fio->StateValue(solid_size);
2669 state_fio->StateValue(solid_mfm);
2670 state_fio->StateValue(inserted);
2671 state_fio->StateValue(ejected);
2672 state_fio->StateValue(write_protected);
2673 state_fio->StateValue(changed);
2674 state_fio->StateValue(media_type);
2675 state_fio->StateValue(is_special_disk);
2676 state_fio->StateArray(track, sizeof(track), 1);
2677 state_fio->StateValue(sector_num.sd);
2678 state_fio->StateValue(track_mfm);
2679 state_fio->StateValue(invalid_format);
2680 // state_fio->StateValue(no_skew);
2681 state_fio->StateArray(sync_position, sizeof(sync_position), 1);
2682 state_fio->StateArray(am1_position, sizeof(am1_position), 1);
2683 state_fio->StateArray(id_position, sizeof(id_position), 1);
2684 state_fio->StateArray(data_position, sizeof(data_position), 1);
2685 // state_fio->StateValue(gap3_size);
2687 int offset = state_fio->FgetInt32_LE();
2688 sector = (offset != -1) ? buffer + offset : NULL;
2690 state_fio->FputInt32_LE(sector ? (int)(sector - buffer) : -1);
2692 state_fio->StateValue(sector_size.sd);
2693 state_fio->StateArray(id, sizeof(id), 1);
2694 state_fio->StateValue(density);
2695 state_fio->StateValue(deleted);
2696 state_fio->StateValue(addr_crc_error);
2697 state_fio->StateValue(data_crc_error);
2698 state_fio->StateValue(drive_type);
2699 state_fio->StateValue(drive_rpm);
2700 state_fio->StateValue(drive_mfm);