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) {
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;
1267 // http://www.gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
1268 // t[6]: 0x00 = double-density, 0x40 = single-density
1269 // t[7]: 0x00 = normal, 0x10 = deleted mark
1270 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
1272 deleted = (t[7] != 0);
1273 // if(ignore_crc()) {
1274 // addr_crc_error = false;
1275 // data_crc_error = false;
1277 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
1278 data_crc_error = ((t[8] & 0xf0) == 0xb0);
1281 sector_size.read_2bytes_le_from(t + 14);
1284 void DISK::set_deleted(bool value)
1286 if(sector != NULL) {
1287 uint8_t *t = sector - 0x10;
1288 t[7] = value ? 0x10 : 0;
1289 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
1290 t[8] = (t[8] & 0x0f) | t[7];
1296 void DISK::set_data_crc_error(bool value)
1298 if(sector != NULL) {
1299 uint8_t *t = sector - 0x10;
1300 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
1302 data_crc_error = value;
1305 void DISK::set_data_mark_missing()
1307 if(sector != NULL) {
1308 uint8_t *t = sector - 0x10;
1309 t[8] = (t[8] & 0x0f) | 0xf0;
1312 // addr_crc_error = false;
1313 data_crc_error = false;
1316 bool DISK::format_track(int trk, int side)
1318 if(media_type == MEDIA_TYPE_2D && drive_type == DRIVE_TYPE_2DD) {
1321 return false; // unformat
1325 } else if(media_type == MEDIA_TYPE_2DD && drive_type == DRIVE_TYPE_2D) {
1326 if(trk >= 0) trk <<= 1;
1328 return format_track_tmp(trk, side);
1331 bool DISK::format_track_tmp(int trk, int side)
1333 // disk not inserted or invalid media type
1334 if(!(inserted && check_media_type())) {
1339 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
1340 if(!(0 <= trkside && trkside < 164)) {
1344 // create new empty track
1347 trim_required = false;
1349 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
1351 offset.d = DISK_BUFFER_SIZE;
1352 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
1354 trim_required = true;
1356 track_mfm = drive_mfm;
1361 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)
1363 uint8_t* t = buffer + DISK_BUFFER_SIZE;
1366 for(int i = 0; i < (sector_num.sd - 1); i++) {
1367 t[4] = sector_num.b.l;
1368 t[5] = sector_num.b.h;
1370 data_size.read_2bytes_le_from(t + 14);
1371 t += data_size.sd + 0x10;
1377 t[4] = sector_num.b.l;
1378 t[5] = sector_num.b.h;
1379 t[6] = track_mfm ? 0 : 0x40;
1380 t[7] = deleted ? 0x10 : 0;
1381 t[8] = data_crc_error ? 0xb0 : t[7];
1382 t[14] = (length >> 0) & 0xff;
1383 t[15] = (length >> 8) & 0xff;
1384 memset(t + 16, fill_data, length);
1389 void DISK::sync_buffer()
1393 trim_required = false;
1397 void DISK::trim_buffer()
1399 int max_tracks = 164;
1400 int track_limit = 164;
1401 uint32_t dest_offset = 0x2b0;
1404 memset(tmp_buffer, 0, sizeof(tmp_buffer));
1405 memcpy(tmp_buffer, buffer, 0x20);
1408 if(media_type == MEDIA_TYPE_2D) {
1411 for(int trkside = 0; trkside < 164; trkside++) {
1412 pair_t src_trk_offset;
1413 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1414 if(src_trk_offset.d != 0) {
1416 if(src_trk_offset.d < 0x2b0) {
1417 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1418 if(max_tracks > track_limit) {
1419 max_tracks = track_limit;
1423 if(src_trk_offset.d != 0x2b0) {
1424 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1425 if(max_tracks > 164) {
1426 dest_offset = 0x20 + max_tracks * 4);
1435 for(int trkside = 0; trkside < max_tracks; trkside++) {
1436 pair_t src_trk_offset;
1437 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1439 pair_t dest_trk_offset;
1440 dest_trk_offset.d = 0;
1442 if(IS_VALID_TRACK(src_trk_offset.d)) {
1443 uint8_t* t = buffer + src_trk_offset.d;
1444 pair_t sector_num, data_size;
1445 sector_num.read_2bytes_le_from(t + 4);
1446 if(sector_num.sd != 0) {
1447 dest_trk_offset.d = dest_offset;
1448 for(int i = 0; i < sector_num.sd; i++) {
1449 data_size.read_2bytes_le_from(t + 14);
1450 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
1451 dest_offset += data_size.sd + 0x10;
1452 t += data_size.sd + 0x10;
1456 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
1460 file_size.d = dest_offset;
1461 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
1463 memset(buffer, 0, sizeof(buffer));
1464 memcpy(buffer, tmp_buffer, min((unsigned int)sizeof(buffer), file_size.d));
1467 int DISK::get_max_tracks()
1469 if(drive_type != DRIVE_TYPE_UNK) {
1470 return (drive_type != DRIVE_TYPE_2D) ? 84 : 42;
1471 } else if(inserted) {
1472 return (media_type != MEDIA_TYPE_2D) ? 84 : 42;
1474 return 84; // 2DD or 2HD
1480 if(drive_rpm != 0) {
1482 } else if(inserted) {
1483 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
1485 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
1489 int DISK::get_track_size()
1491 if(track_size != 0) {
1493 } else if(inserted) {
1494 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : track_mfm ? 6250 : 3100;
1496 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
1500 double DISK::get_usec_per_track()
1502 return 1000000.0 / (get_rpm() / 60.0);
1505 double DISK::get_usec_per_bytes(int bytes)
1507 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1510 int DISK::get_bytes_per_usec(double usec)
1512 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1515 bool DISK::check_media_type()
1517 switch(drive_type) {
1519 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1520 case DRIVE_TYPE_2DD:
1521 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1522 case DRIVE_TYPE_2HD:
1523 return (media_type == MEDIA_TYPE_2HD);
1524 case DRIVE_TYPE_144:
1525 return (media_type == MEDIA_TYPE_144);
1526 case DRIVE_TYPE_UNK:
1527 return true; // always okay
1534 #define COPYBUFFER(src, size) { \
1535 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1538 memcpy(buffer + file_size.d, (src), (size)); \
1539 file_size.d += (size); \
1548 uint32_t trkptr[164];
1554 uint8_t dens, del, stat;
1559 // teledisk image decoder
1562 this teledisk image decoder is based on:
1564 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1565 LZSS coded by Haruhiko OKUMURA
1566 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1567 Edited and translated to English by Kenji RIKITAKE
1571 #define STRING_BUFFER_SIZE 4096
1572 #define LOOKAHEAD_BUFFER_SIZE 60
1574 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1575 #define TABLE_SIZE (N_CHAR * 2 - 1)
1576 #define ROOT_POSITION (TABLE_SIZE - 1)
1577 #define MAX_FREQ 0x8000
1579 static uint8_t td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1580 static uint16_t td_ptr;
1581 static uint16_t td_bufcnt, td_bufndx, td_bufpos;
1582 static uint16_t td_ibufcnt, td_ibufndx;
1583 static uint8_t td_inbuf[512];
1584 static uint16_t td_freq[TABLE_SIZE + 1];
1585 static short td_prnt[TABLE_SIZE + N_CHAR];
1586 static short td_son[TABLE_SIZE];
1587 static uint16_t td_getbuf;
1588 static uint8_t td_getlen;
1590 static const uint8_t td_d_code[256] = {
1591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1593 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1594 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1595 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1596 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1597 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1598 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1599 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1600 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1601 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1602 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1603 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1604 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1605 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1606 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1608 static const uint8_t td_d_len[256] = {
1609 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1610 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1611 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1612 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1613 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1614 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1615 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1616 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1617 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1618 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1619 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1620 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1621 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1622 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1623 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1624 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1627 static int td_next_word(FILEIO* fio)
1629 if(td_ibufndx >= td_ibufcnt) {
1630 td_ibufndx = td_ibufcnt = 0;
1631 memset(td_inbuf, 0, 512);
1632 for(int i = 0; i < 512; i++) {
1633 int d = fio->Fgetc();
1644 while(td_getlen <= 8) {
1645 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1651 static int td_get_bit(FILEIO* fio)
1653 if(td_next_word(fio) < 0) {
1656 short i = td_getbuf;
1659 return (i < 0) ? 1 : 0;
1662 static int td_get_byte(FILEIO* fio)
1664 if(td_next_word(fio) != 0) {
1667 uint16_t i = td_getbuf;
1674 static void td_start_huff()
1677 for(i = 0; i < N_CHAR; i++) {
1679 td_son[i] = i + TABLE_SIZE;
1680 td_prnt[i + TABLE_SIZE] = i;
1683 while(j <= ROOT_POSITION) {
1684 td_freq[j] = td_freq[i] + td_freq[i + 1];
1686 td_prnt[i] = td_prnt[i + 1] = j;
1689 td_freq[TABLE_SIZE] = 0xffff;
1690 td_prnt[ROOT_POSITION] = 0;
1693 static void td_reconst()
1697 for(i = 0; i < TABLE_SIZE; i++) {
1698 if(td_son[i] >= TABLE_SIZE) {
1699 td_freq[j] = (td_freq[i] + 1) / 2;
1700 td_son[j] = td_son[i];
1704 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1706 f = td_freq[j] = td_freq[i] + td_freq[k];
1707 for(k = j - 1; f < td_freq[k]; k--);
1710 memmove(&td_freq[k + 1], &td_freq[k], l);
1712 memmove(&td_son[k + 1], &td_son[k], l);
1715 for(i = 0; i < TABLE_SIZE; i++) {
1716 if((k = td_son[i]) >= TABLE_SIZE) {
1719 td_prnt[k] = td_prnt[k + 1] = i;
1724 static void td_update(int c)
1727 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1730 c = td_prnt[c + TABLE_SIZE];
1733 if(k > td_freq[l = c + 1]) {
1734 while(k > td_freq[++l]);
1736 td_freq[c] = td_freq[l];
1740 if(i < TABLE_SIZE) {
1746 if(j < TABLE_SIZE) {
1753 while((c = td_prnt[c]) != 0);
1756 static short td_decode_char(FILEIO* fio)
1759 uint16_t c = td_son[ROOT_POSITION];
1760 while(c < TABLE_SIZE) {
1761 if((ret = td_get_bit(fio)) < 0) {
1772 static short td_decode_position(FILEIO* fio)
1776 if((bit = td_get_byte(fio)) < 0) {
1780 c = (uint16_t)td_d_code[i] << 6;
1781 j = td_d_len[i] - 2;
1783 if((bit = td_get_bit(fio)) < 0) {
1788 return (c | (i & 0x3f));
1791 static void td_init_decode()
1793 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1796 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1797 td_text_buf[i] = ' ';
1799 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1802 static int td_decode(FILEIO* fio, uint8_t *buf, int len)
1806 for(count = 0; count < len;) {
1807 if(td_bufcnt == 0) {
1808 if((c = td_decode_char(fio)) < 0) {
1812 *(buf++) = (uint8_t)c;
1813 td_text_buf[td_ptr++] = (uint8_t)c;
1814 td_ptr &= (STRING_BUFFER_SIZE - 1);
1817 if((pos = td_decode_position(fio)) < 0) {
1820 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1821 td_bufcnt = c - 255 + THRESHOLD;
1825 while(td_bufndx < td_bufcnt && count < len) {
1826 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1827 *(buf++) = (uint8_t)c;
1829 td_text_buf[td_ptr++] = (uint8_t)c;
1830 td_ptr &= (STRING_BUFFER_SIZE - 1);
1833 if(td_bufndx >= td_bufcnt) {
1834 td_bufndx = td_bufcnt = 0;
1861 uint8_t nsec, trk, head;
1870 bool DISK::teledisk_to_d88(FILEIO *fio)
1877 bool temporary = false;
1879 // check teledisk header
1880 fio->Fseek(0, FILEIO_SEEK_SET);
1881 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1882 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1883 // this image is compressed
1884 // decompress to the temporary file
1885 FILEIO* fio_tmp = new FILEIO();
1886 if(!fio_tmp->Fopen(local_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1893 if((rd = td_decode(fio, obuf, 512)) > 0) {
1894 fio_tmp->Fwrite(obuf, rd, 1);
1902 // reopen the temporary file
1904 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1907 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1908 // this image is not compressed
1912 if(hdr.flag & 0x80) {
1914 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1915 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1918 // create d88 header
1922 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1923 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1924 d88_hdr.protect = 0; // non-protected
1927 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1930 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1931 fio->Fread(&trk, sizeof(td_trk_t), 1);
1932 while(trk.nsec != 0xff) {
1933 d88_hdr.trkptr[trkcnt++] = trkptr;
1934 if(hdr.sides == 1) {
1938 // read sectors in this track
1939 for(int i = 0; i < trk.nsec; i++) {
1940 uint8_t buf[2048], dst[2048];
1941 memset(buf, 0, sizeof(buf));
1942 memset(dst, 0, sizeof(dst));
1944 // read sector header
1945 fio->Fread(&sct, sizeof(td_sct_t), 1);
1947 // create d88 sector header
1948 memset(&d88_sct, 0, sizeof(d88_sct_t));
1953 d88_sct.nsec = trk.nsec;
1954 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1955 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1956 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1957 d88_sct.size = secsize[sct.n & 3];
1959 // create sector image
1960 if(sct.ctrl & 0x30) {
1961 d88_sct.stat = 0xf0; // data mark missing
1964 // read sector source
1965 int len = fio->Fgetc();
1966 len += fio->Fgetc() * 256 - 1;
1967 int flag = fio->Fgetc(), d = 0;
1968 fio->Fread(buf, len, 1);
1972 memcpy(dst, buf, len);
1973 } else if(flag == 1) {
1975 len2.read_2bytes_le_from(buf);
1980 } else if(flag == 2) {
1981 for(int s = 0; s < len;) {
1982 int type = buf[s++];
1983 int len2 = buf[s++];
1986 dst[d++] = buf[s++];
1988 } else if(type < 5) {
1994 for(int j = 0; j < n; j++) {
1998 for(int j = 0; j < n; j++) {
2003 break; // unknown type
2007 break; // unknown flag
2012 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2013 COPYBUFFER(dst, d88_sct.size);
2014 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2017 fio->Fread(&trk, sizeof(td_trk_t), 1);
2019 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
2020 d88_hdr.size = trkptr;
2021 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2024 FILEIO::RemoveFile(_T("teledisk.$$$"));
2029 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
2031 bool DISK::imagedisk_to_d88(FILEIO *fio)
2033 int size = fio->FileLength();
2034 fio->Fseek(0, FILEIO_SEEK_SET);
2035 fio->Fread(tmp_buffer, size, 1);
2037 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
2042 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
2049 // create d88 header
2053 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2054 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
2055 d88_hdr.protect = 0; // non-protected
2058 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2061 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
2066 // check track header
2067 uint8_t mode = tmp_buffer[pos++];
2068 uint8_t track = tmp_buffer[pos++];
2069 uint8_t head = tmp_buffer[pos++];
2070 uint8_t sector_count = tmp_buffer[pos++];
2071 uint8_t ssize = tmp_buffer[pos++];
2073 if(sector_count == 0) {
2079 uint32_t actual_size = ssize < 7 ? 128 << ssize : 8192;
2082 const uint8_t *snum = &tmp_buffer[pos];
2083 pos += sector_count;
2084 const uint8_t *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
2086 pos += sector_count;
2087 const uint8_t *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
2089 pos += sector_count;
2093 int trkside = track * 2 + (head & 1);
2095 if(trkcnt < trkside) {
2098 d88_hdr.trkptr[trkside] = trkptr;
2100 if(img_mode == -1) {
2101 img_mode = mode & 3;
2104 // read sectors in this track
2105 for(int i = 0; i < sector_count; i++) {
2106 // create d88 sector header
2107 uint8_t stype = tmp_buffer[pos++];
2108 memset(&d88_sct, 0, sizeof(d88_sct_t));
2109 d88_sct.c = tnum ? tnum[i] : track;
2110 d88_sct.h = hnum ? hnum[i] : head;
2111 d88_sct.r = snum[i];
2113 d88_sct.nsec = sector_count;
2114 d88_sct.dens = (mode < 3) ? 0x40 : 0;
2116 if(stype == 0 || stype > 8) {
2117 d88_sct.stat = 0xf0; // data mark missing
2120 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
2121 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
2122 d88_sct.size = actual_size;
2124 // create sector image
2125 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
2126 memset(dst, tmp_buffer[pos++], actual_size);
2128 memcpy(dst, &tmp_buffer[pos], actual_size);
2129 pos += d88_sct.size;
2135 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2136 COPYBUFFER(dst, d88_sct.size);
2137 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2141 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
2142 d88_hdr.size = trkptr;
2143 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2147 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
2149 #define DSK_FORMAT_HEADER "MV - CPC"
2150 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
2153 struct track_header {
2154 uint8_t headertag[13];
2157 uint8_t track_number;
2158 uint8_t side_number;
2161 uint8_t sector_size_code;
2162 uint8_t number_of_sector;
2163 uint8_t gap3_length;
2164 uint8_t filler_byte;
2166 struct sector_header {
2170 uint8_t sector_size_code;
2171 uint8_t fdc_status_reg1;
2172 uint8_t fdc_status_reg2;
2173 uint16_t data_length;
2177 bool DISK::cpdread_to_d88(FILEIO *fio)
2179 bool extendformat = false;
2180 int image_size = fio->FileLength();
2182 fio->Fseek(0, FILEIO_SEEK_SET);
2183 fio->Fread(tmp_buffer, image_size, 1);
2185 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
2186 extendformat = true;
2187 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
2188 extendformat = false;
2193 int heads = tmp_buffer[0x31];
2198 int tracks = tmp_buffer[0x30];
2199 int track_offsets[84 * 2];
2200 bool track_offsets_error = false;
2202 int cnt = 0, tmp = 0x100;
2203 for(int i = 0; i < tracks * heads; i++) {
2204 track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0);
2205 if(track_offsets_error) {
2208 track_offsets[cnt] = tmp;
2209 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
2213 int cnt = 0, tmp = 0x100;
2214 for(int i = 0; i < tracks * heads; i++) {
2215 int length = tmp_buffer[0x34 + i] << 8;
2217 track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0);
2218 if(track_offsets_error) {
2221 track_offsets[cnt] = tmp;
2224 track_offsets[cnt] = image_size;
2229 if(track_offsets_error) {
2230 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
2231 // so I modified this code to search "Track-Info" at the top of track information block
2232 int cnt = 0, tmp = 0x100;
2233 for(int i = 0; i < tracks * heads; i++) {
2235 for(; tmp < image_size; tmp += 0x10) {
2236 found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0);
2242 track_offsets[cnt] = tmp;
2245 track_offsets[cnt] = image_size;
2251 // create d88 header
2255 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2256 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
2257 d88_hdr.protect = 0; // non-protected
2260 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2263 int total = 0, trkptr = sizeof(d88_hdr_t);
2265 for(int track = 0; track < tracks; track++) {
2266 for(int side = 0; side < heads; side++) {
2267 if(track_offsets[(track << 1) + side] >= image_size) {
2270 if((track << 1) + side < 164) {
2271 d88_hdr.trkptr[(track << 1) + side] = trkptr;
2275 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
2276 int pos = track_offsets[(track << 1) + side] + 0x100;
2277 for(int j = 0; j < tr.number_of_sector; j++) {
2278 sector_header sector;
2279 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
2281 // create d88 sector header
2282 memset(&d88_sct, 0, sizeof(d88_sct_t));
2283 d88_sct.c = sector.track;
2284 d88_sct.h = sector.side;
2285 d88_sct.r = sector.sector_id;
2286 d88_sct.n = sector.sector_size_code;
2287 d88_sct.nsec = tr.number_of_sector;
2289 d88_sct.size = sector.data_length;
2290 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
2292 d88_sct.size = 128 << tr.sector_size_code;
2293 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
2295 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
2296 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
2299 if((track << 1) + side < 164) {
2300 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2301 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
2302 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2304 total += d88_sct.size;
2307 pos += sector.data_length;
2309 pos += 128 << tr.sector_size_code;
2314 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
2315 d88_hdr.size = trkptr;
2316 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2320 // nfd r0/r1 image decoder
2322 bool DISK::nfdr0_to_d88(FILEIO *fio)
2324 // from NFD r0
\8c`
\8e®
\83t
\83@
\83C
\83\8b\8d\
\91¢
\8ed
\97l 2001/01/22 LED
2326 BYTE C; // C
\81i0xFF
\82Ì
\8e\9e\83Z
\83N
\83^
\96³
\82µ
\81j
2330 BYTE flMFM; // 0:FM / 1:MFM
2331 BYTE flDDAM; // 0:DAM / 1:DDAM
2332 BYTE byStatus; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê
2333 BYTE byST0; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST0
2334 BYTE byST1; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST1
2335 BYTE byST2; // READ DATA(FDDBIOS)
\82Ì
\8c\8b\89Ê ST2
2336 BYTE byPDA; // FDDBIOS
\82Å
\8eg
\97p
\82·
\82é
\83A
\83h
\83\8c\83X
2337 char Reserve1[5]; //
\97\
\96ñ
2338 }NFD_SECT_ID,*LP_NFD_SECT_ID;
2341 char szFileID[15]; //
\8e¯
\95ÊID "T98FDDIMAGE.R0"
2342 char Reserve1[1]; //
\97\
\96ñ
2343 char szComment[0x100]; //
\83C
\83\81\81[
\83W
\83R
\83\81\83\93\83g(ASCIIz)
2344 DWORD dwHeadSize; //
\83w
\83b
\83_
\95\94\82Ì
\83T
\83C
\83Y
2345 BYTE flProtect; // 0
\88È
\8aO :
\83\89\83C
\83g
\83v
\83\8d\83e
\83N
\83g
2346 BYTE byHead; //
\83w
\83b
\83h
\90\94
2347 char Reserve2[10]; //
\97\
\96ñ
2348 NFD_SECT_ID si[163][26]; //
\83Z
\83N
\83^ID(
\8cã
\8fq)
2349 char Reserve3[0x10]; //
\97\
\96ñ
2350 }NFD_FILE_HEAD,*LP_NFD_FILE_HEAD;
2355 fio->Fseek(0, FILEIO_SEEK_SET);
2356 fio->Fread(&head, sizeof(head), 1);
2358 if(strncmp(head.szFileID, "T98FDDIMAGE.R0", 14) != 0) {
2361 fio->Fseek(head.dwHeadSize, FILEIO_SEEK_SET);
2363 // create d88 header
2367 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2368 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "NFD R0");
2369 d88_hdr.protect = head.flProtect;
2372 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2375 int trkptr = sizeof(d88_hdr_t);
2377 for(int c = 0; c < 163; c++) {
2380 for(int s = 0; s < 26; s++) {
2381 if(head.si[c][s].C != 0xff) {
2386 d88_hdr.trkptr[c] = trkptr;
2388 // read sectors in this track
2389 for(int s = 0; s < 26; s++) {
2390 if(head.si[c][s].C != 0xff) {
2391 // create d88 sector header
2392 memset(&d88_sct, 0, sizeof(d88_sct_t));
2393 d88_sct.c = head.si[c][s].C;
2394 d88_sct.h = head.si[c][s].H;
2395 d88_sct.r = head.si[c][s].R;
2396 d88_sct.n = head.si[c][s].N;
2397 d88_sct.nsec = nsec;
2398 d88_sct.dens = head.si[c][s].flMFM ? 0 : 0x40;
2399 d88_sct.del = head.si[c][s].flDDAM ? 0x10 : 0;
2400 if(head.si[c][s].byST1 & 0x20) {
2401 if(head.si[c][s].byST2 & 0x20) {
2402 d88_sct.stat = 0xb0; // data crc error
2404 d88_sct.stat = 0xa0; // id crc error
2406 } else if(head.si[c][s].byST1 & 0x01) {
2407 d88_sct.stat = 0xe0; // address mark missing
2408 } else if(head.si[c][s].byST2 & 0x01) {
2409 d88_sct.stat = 0xf0; // data mark missing
2411 d88_sct.stat = d88_sct.del;
2413 d88_sct.size = secsize[d88_sct.n & 3];
2415 // create sector image
2417 memset(dst, 0xe5, sizeof(dst));
2418 fio->Fread(dst, d88_sct.size, 1);
2421 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2422 COPYBUFFER(dst, d88_sct.size);
2423 trkptr += sizeof(d88_sct_t) + d88_sct.size;
2425 if(head.si[c][s].byPDA == 0x10) {
2426 d88_hdr.type = MEDIA_TYPE_2DD;
2428 d88_hdr.type = MEDIA_TYPE_2HD;
2434 d88_hdr.size = trkptr;
2435 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2439 bool DISK::nfdr1_to_d88(FILEIO *fio)
2441 // from NFD r1
\8c`
\8e®
\83t
\83@
\83C
\83\8b\8d\
\91¢
\8ed
\97l 2001/09/14 LED
2443 // char szFileID[sizeof(NFD_FILE_ID1)]; /*
\8e¯
\95ÊID "T98FDDIMAGE.R1" */
2444 // char Reserv1[0x10-sizeof(NFD_FILE_ID1)]; /*
\97\
\94õ */
2445 char szFileID[15]; /*
\8e¯
\95ÊID "T98FDDIMAGE.R1" */
2446 char Reserve1[1]; /*
\97\
\96ñ */
2447 char szComment[0x100]; /*
\83R
\83\81\83\93\83g */
2448 DWORD dwHeadSize; /*
\83w
\83b
\83_
\82Ì
\83T
\83C
\83Y */
2449 BYTE flProtect; /*
\83\89\83C
\83g
\83v
\83\8d\83e
\83N
\83g0
\88È
\8aO */
2450 BYTE byHead; /*
\83w
\83b
\83h
\90\94 1-2 */
2451 char Reserv2[0x10-4-1-1]; /*
\97\
\94õ */
2452 DWORD dwTrackHead[164]; /*
\83g
\83\89\83b
\83NID
\88Ê
\92u */
2453 DWORD dwAddInfo; /*
\92Ç
\89Á
\8fî
\95ñ
\83w
\83b
\83_
\82Ì
\83A
\83h
\83\8c\83X */
2454 char Reserv3[0x10-4]; /*
\97\
\94õ */
2455 }NFD_FILE_HEAD1,*LP_NFD_FILE_HEAD1;
2458 WORD wSector; /*
\83Z
\83N
\83^ID
\90\94 */
2459 WORD wDiag; /*
\93Á
\8eê ID
\90\94 */
2460 char Reserv1[0x10-4]; /*
\97\
\94õ */
2461 }NFD_TRACK_ID1,*LP_NFD_TRACK_ID1;
2468 BYTE flMFM; /* MFM(1)/FM(0) */
2469 BYTE flDDAM; /* DDAM(1)/DAM(0) */
2470 BYTE byStatus; /* READ DATA RESULT */
2471 BYTE bySTS0; /* ST0 */
2472 BYTE bySTS1; /* ST1 */
2473 BYTE bySTS2; /* ST2 */
2474 BYTE byRetry; /* RetryData
\82È
\82µ(0)
\82 \82è(1-) */
2475 BYTE byPDA; /* PDA */
2476 char Reserv1[0x10-12]; /*
\97\
\94õ */
2477 }NFD_SECT_ID1,*LP_NFD_SECT_ID1;
2480 BYTE Cmd; /* Command */
2485 BYTE byStatus; /* READ DATA RESULT */
2486 BYTE bySTS0; /* ST0 */
2487 BYTE bySTS1; /* ST1 */
2488 BYTE bySTS2; /* ST2 */
2489 BYTE byRetry; /* RetryData
\82È
\82µ(0)
\82 \82è(1-) */
2491 BYTE byPDA; /* PDA */
2492 char Reserv1[0x10-15]; /*
\97\
\94õ */
2493 }NFD_DIAG_ID1,*LP_NFD_DIAG_ID1;
2496 NFD_FILE_HEAD1 head;
2498 fio->Fseek(0, FILEIO_SEEK_SET);
2499 fio->Fread(&head, sizeof(head), 1);
2501 if(strncmp(head.szFileID, "T98FDDIMAGE.R1", 14) != 0) {
2504 fio->Fseek(head.dwHeadSize, FILEIO_SEEK_SET);
2506 // not implemented yet :-(
2510 // solid image decoder
2512 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
2518 solid_nside = nside;
2523 // create d88 header
2527 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
2528 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
2529 d88_hdr.protect = 0; // non-protected
2532 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
2535 for(int i = 0; i < 8; i++) {
2536 if(size == (128 << i)) {
2543 int trkptr = sizeof(d88_hdr_t);
2545 for(int c = 0; c < ncyl; c++) {
2546 for(int h = 0; h < nside; h++) {
2547 d88_hdr.trkptr[t++] = trkptr;
2552 // read sectors in this track
2553 for(int s = 0; s < nsec; s++) {
2554 // create d88 sector header
2555 memset(&d88_sct, 0, sizeof(d88_sct_t));
2560 d88_sct.nsec = nsec;
2564 d88_sct.size = size;
2566 // create sector image
2568 memset(dst, 0xe5, sizeof(dst));
2569 fio->Fread(dst, size, 1);
2572 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2573 COPYBUFFER(dst, size);
2574 trkptr += sizeof(d88_sct_t) + size;
2578 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
2579 d88_hdr.size = trkptr;
2580 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2584 #define STATE_VERSION 14
2586 #include "../../statesub.h"
2587 #include "../../qt/gui/csp_logger.h"
2589 void DISK::decl_state(void *p)
2591 CSP_Logger *p_logger = (CSP_Logger *)p;
2592 state_entry = new csp_state_utils(STATE_VERSION, drive_num, _T("FLOPPY_DISK"), p_logger);
2594 DECL_STATE_ENTRY_1D_ARRAY(buffer, sizeof(buffer));
2595 DECL_STATE_ENTRY_STRING(orig_path, sizeof(orig_path) / sizeof(_TCHAR));
2596 DECL_STATE_ENTRY_STRING(dest_path, sizeof(dest_path) / sizeof(_TCHAR));
2598 DECL_STATE_ENTRY_PAIR(file_size);
2599 DECL_STATE_ENTRY_INT32(file_bank);
2600 DECL_STATE_ENTRY_UINT32(orig_file_size);
2601 DECL_STATE_ENTRY_UINT32(orig_crc32);
2602 DECL_STATE_ENTRY_BOOL(trim_required);
2603 DECL_STATE_ENTRY_BOOL(is_1dd_image);
2604 DECL_STATE_ENTRY_BOOL(is_solid_image);
2605 DECL_STATE_ENTRY_BOOL(is_fdi_image);
2607 DECL_STATE_ENTRY_1D_ARRAY(fdi_header, sizeof(fdi_header));
2609 DECL_STATE_ENTRY_INT32(solid_ncyl);
2610 DECL_STATE_ENTRY_INT32(solid_nside);
2611 DECL_STATE_ENTRY_INT32(solid_nsec);
2612 DECL_STATE_ENTRY_INT32(solid_size);
2613 DECL_STATE_ENTRY_BOOL(solid_mfm);
2614 DECL_STATE_ENTRY_BOOL(inserted);
2615 DECL_STATE_ENTRY_BOOL(ejected);
2616 DECL_STATE_ENTRY_BOOL(write_protected);
2617 DECL_STATE_ENTRY_BOOL(changed);
2618 DECL_STATE_ENTRY_UINT8(media_type);
2619 DECL_STATE_ENTRY_INT32(is_special_disk);
2621 DECL_STATE_ENTRY_1D_ARRAY(track, sizeof(track));
2623 DECL_STATE_ENTRY_PAIR(sector_num);
2624 DECL_STATE_ENTRY_BOOL(track_mfm);
2625 DECL_STATE_ENTRY_BOOL(invalid_format);
2626 // DECL_STATE_ENTRY_BOOL(no_skew);
2627 DECL_STATE_ENTRY_1D_ARRAY(sync_position, sizeof(sync_position) / sizeof(int));
2628 DECL_STATE_ENTRY_1D_ARRAY(am1_position, sizeof(am1_position) / sizeof(int));
2629 DECL_STATE_ENTRY_1D_ARRAY(id_position, sizeof(id_position) / sizeof(int));
2630 DECL_STATE_ENTRY_1D_ARRAY(data_position, sizeof(data_position) / sizeof(int));
2631 // DECL_STATE_ENTRY_INT32(gap3_size);
2632 DECL_STATE_ENTRY_INT32(_tmp_sector_offset);
2633 DECL_STATE_ENTRY_PAIR(sector_size);
2635 DECL_STATE_ENTRY_1D_ARRAY(id, sizeof(id));
2636 DECL_STATE_ENTRY_UINT8(density);
2637 DECL_STATE_ENTRY_BOOL(deleted);
2638 DECL_STATE_ENTRY_BOOL(addr_crc_error);
2639 DECL_STATE_ENTRY_BOOL(data_crc_error);
2640 DECL_STATE_ENTRY_UINT8(drive_type);
2641 DECL_STATE_ENTRY_INT32(drive_rpm);
2642 DECL_STATE_ENTRY_BOOL(drive_mfm);
2644 void DISK::save_state(FILEIO* state_fio)
2646 _tmp_sector_offset = (sector != NULL) ? (int)(sector - buffer) : -1;
2648 if(state_entry != NULL) {
2649 state_entry->save_state(state_fio);
2651 //state_fio->FputUint32(STATE_VERSION);
2653 //state_fio->Fwrite(buffer, sizeof(buffer), 1);
2654 //state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
2655 //state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
2656 //state_fio->FputUint32(file_size.d);
2657 //state_fio->FputInt32(file_bank);
2658 //state_fio->FputUint32(orig_file_size);
2659 //state_fio->FputUint32(orig_crc32);
2660 //state_fio->FputBool(trim_required);
2661 //state_fio->FputBool(is_1dd_image);
2662 //state_fio->FputBool(is_solid_image);
2663 //state_fio->FputBool(is_fdi_image);
2664 //state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
2665 //state_fio->FputInt32(solid_ncyl);
2666 //state_fio->FputInt32(solid_nside);
2667 //state_fio->FputInt32(solid_nsec);
2668 //state_fio->FputInt32(solid_size);
2669 //state_fio->FputBool(solid_mfm);
2670 //state_fio->FputBool(inserted);
2671 //state_fio->FputBool(ejected);
2672 //state_fio->FputBool(write_protected);
2673 //state_fio->FputBool(changed);
2674 //state_fio->FputUint8(media_type);
2675 //state_fio->FputInt32(is_special_disk);
2676 //state_fio->Fwrite(track, sizeof(track), 1);
2677 //state_fio->FputInt32(sector_num.sd);
2678 //state_fio->FputBool(track_mfm);
2679 //state_fio->FputBool(invalid_format);
2680 // state_fio->FputBool(no_skew);
2681 //state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
2682 //state_fio->Fwrite(am1_position, sizeof(am1_position), 1);
2683 //state_fio->Fwrite(id_position, sizeof(id_position), 1);
2684 //state_fio->Fwrite(data_position, sizeof(data_position), 1);
2685 // state_fio->FputInt32(gap3_size);
2686 //state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
2687 //state_fio->FputInt32(sector_size.sd);
2688 //state_fio->Fwrite(id, sizeof(id), 1);
2689 //state_fio->FputUint8(density);
2690 //state_fio->FputBool(deleted);
2691 //state_fio->FputBool(addr_crc_error);
2692 //state_fio->FputBool(data_crc_error);
2693 //state_fio->FputUint8(drive_type);
2694 //state_fio->FputInt32(drive_rpm);
2695 //state_fio->FputBool(drive_mfm);
2698 bool DISK::load_state(FILEIO* state_fio)
2701 if(state_entry != NULL) {
2702 mb = state_entry->load_state(state_fio);
2704 if(!mb) return false;
2705 //if(state_fio->FgetUint32() != STATE_VERSION) {
2708 //state_fio->Fread(buffer, sizeof(buffer), 1);
2709 //state_fio->Fread(orig_path, sizeof(orig_path), 1);
2710 //state_fio->Fread(dest_path, sizeof(dest_path), 1);
2711 //file_size.d = state_fio->FgetUint32();
2712 //file_bank = state_fio->FgetInt32();
2713 //orig_file_size = state_fio->FgetUint32();
2714 //orig_crc32 = state_fio->FgetUint32();
2715 //trim_required = state_fio->FgetBool();
2716 //is_1dd_image = state_fio->FgetBool();
2717 //is_solid_image = state_fio->FgetBool();
2718 //is_fdi_image = state_fio->FgetBool();
2719 //state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
2720 //solid_ncyl = state_fio->FgetInt32();
2721 //solid_nside = state_fio->FgetInt32();
2722 //solid_nsec = state_fio->FgetInt32();
2723 //solid_size = state_fio->FgetInt32();
2724 //solid_mfm = state_fio->FgetBool();
2725 //inserted = state_fio->FgetBool();
2726 //ejected = state_fio->FgetBool();
2727 //write_protected = state_fio->FgetBool();
2728 //changed = state_fio->FgetBool();
2729 //media_type = state_fio->FgetUint8();
2730 //is_special_disk = state_fio->FgetInt32();
2731 //state_fio->Fread(track, sizeof(track), 1);
2732 //sector_num.sd = state_fio->FgetInt32();
2733 //track_mfm = state_fio->FgetBool();
2734 //invalid_format = state_fio->FgetBool();
2735 // no_skew = state_fio->FgetBool();
2736 //state_fio->Fread(sync_position, sizeof(sync_position), 1);
2737 //state_fio->Fread(am1_position, sizeof(am1_position), 1);
2738 //state_fio->Fread(id_position, sizeof(id_position), 1);
2739 //state_fio->Fread(data_position, sizeof(data_position), 1);
2740 // gap3_size = state_fio->FgetInt32();
2741 //int offset = state_fio->FgetInt32();
2742 //sector = (offset != -1) ? buffer + offset : NULL;
2743 //sector_size.sd = state_fio->FgetInt32();
2744 //state_fio->Fread(id, sizeof(id), 1);
2745 //density = state_fio->FgetUint8();
2746 //deleted = state_fio->FgetBool();
2747 //addr_crc_error = state_fio->FgetBool();
2748 //data_crc_error = state_fio->FgetBool();
2749 //drive_type = state_fio->FgetUint8();
2750 //drive_rpm = state_fio->FgetInt32();
2751 //drive_mfm = state_fio->FgetBool();
2752 sector = (_tmp_sector_offset != -1) ? (buffer + _tmp_sector_offset) : NULL;