2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 #include "../fileio.h"
14 #define local_path(x) create_local_path(x)
16 #define local_path(x) (x)
20 static const uint16 crc_table[256] = {
21 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
22 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
23 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
24 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
25 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
26 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
27 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
28 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
29 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
30 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
31 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
32 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
33 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
34 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
35 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
36 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
39 static const int secsize[8] = {
40 128, 256, 512, 1024, 2048, 4096, 8192, 16384
43 static uint8 tmp_buffer[DISK_BUFFER_SIZE];
45 // physical format table for solid image
48 int ncyl, nside, nsec, size;
55 static const fd_format_t fd_formats[] = {
57 { MEDIA_TYPE_2D, 40, 1, 16, 256, MFM }, // 1D 160KB
58 #elif defined(_SMC70) || defined(_SMC777)
59 { MEDIA_TYPE_2DD, 70, 1, 16, 256, MFM }, // 1DD 280KB
60 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
61 { MEDIA_TYPE_2D, 40, 2, 16, 256, MFM }, // 2D 320KB
63 { MEDIA_TYPE_2D, 40, 2, 18, 256, MFM }, // 2D 360KB
64 #elif defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200) || defined(_MZ2500)
65 { MEDIA_TYPE_2DD, 80, 2, 16, 256, MFM }, // 2DD 640KB
67 { MEDIA_TYPE_2D, 35, 1, 16, 128, FM }, // 1S 70KB
68 { MEDIA_TYPE_2D, 35, 2, 16, 128, FM }, // 2S 140KB
69 { MEDIA_TYPE_2DD, 77, 1, 26, 128, FM }, // 1S 250KB
70 { MEDIA_TYPE_2D, 40, 1, 8, 512, MFM }, // 1D 160KB
71 { MEDIA_TYPE_2D, 40, 1, 9, 512, MFM }, // 1D 180KB
72 { MEDIA_TYPE_2D, 40, 1, 10, 512, MFM }, // 1D 200KB
73 //#if defined(SUPPORT_MEDIA_TYPE_1DD)
74 // { MEDIA_TYPE_2DD, 70, 1, 8, 512, MFM }, // 1DD 280KB
75 // { MEDIA_TYPE_2DD, 70, 1, 9, 512, MFM }, // 1DD 315KB
76 // { MEDIA_TYPE_2DD, 70, 1, 10, 512, MFM }, // 1DD 350KB
77 // { MEDIA_TYPE_2DD, 80, 1, 8, 512, MFM }, // 1DD 320KB
78 // { MEDIA_TYPE_2DD, 80, 1, 9, 512, MFM }, // 1DD 360KB
79 // { MEDIA_TYPE_2DD, 80, 1, 10, 512, MFM }, // 1DD 400KB
81 { MEDIA_TYPE_2D, 35, 2, 8, 512, MFM }, // 2D 280KB
82 { MEDIA_TYPE_2D, 35, 2, 9, 512, MFM }, // 2D 315KB
83 { MEDIA_TYPE_2D, 35, 2, 10, 512, MFM }, // 2D 350KB
84 { MEDIA_TYPE_2D, 40, 2, 8, 512, MFM }, // 2D 320KB
85 { MEDIA_TYPE_2D, 40, 2, 9, 512, MFM }, // 2D 360KB
86 { MEDIA_TYPE_2D, 40, 2, 10, 512, MFM }, // 2D 400KB
88 { MEDIA_TYPE_2DD, 80, 2, 8, 512, MFM }, // 2DD 640KB
89 { MEDIA_TYPE_2DD, 80, 2, 9, 512, MFM }, // 2DD 720KB
90 { MEDIA_TYPE_2DD, 81, 2, 9, 512, MFM }, // 2DD 729KB, ASCII MSX
91 { MEDIA_TYPE_2DD, 80, 2, 10, 512, MFM }, // 2DD 800KB
92 { MEDIA_TYPE_2HD, 77, 2, 26, 256, MFM }, // 2HD 1001KB, MITSUBISHI/IBM
93 { MEDIA_TYPE_2HD, 80, 2, 15, 512, MFM }, // 2HC 1200KB, TOSHIBA/IBM
94 { MEDIA_TYPE_2HD, 77, 2, 8, 1024, MFM }, // 2HD 1232KB, NEC
95 { MEDIA_TYPE_144, 80, 2, 18, 512, MFM }, // 2HD 1440KB
96 { MEDIA_TYPE_144, 80, 2, 21, 512, MFM }, // 2HD 1680KB
97 { MEDIA_TYPE_144, 82, 2, 21, 512, MFM }, // 2HD 1722KB
98 { MEDIA_TYPE_144, 80, 2, 36, 512, MFM }, // 2ED 2880KB
102 #define IS_VALID_TRACK(offset) ((offset) >= 0x20 && (offset) < sizeof(buffer))
104 void DISK::open(const _TCHAR* file_path, int bank)
106 // check current disk image
108 if(_tcsicmp(orig_path, file_path) == 0 && file_bank == bank) {
116 memset(buffer, 0, sizeof(buffer));
118 write_protected = false;
119 media_type = MEDIA_TYPE_UNK;
121 is_solid_image = is_fdi_image = is_1dd_image = false;
122 trim_required = false;
123 track_mfm = drive_mfm;
126 FILEIO *fio = new FILEIO();
127 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
128 my_tcscpy_s(orig_path, _MAX_PATH, file_path);
129 my_tcscpy_s(dest_path, _MAX_PATH, file_path);
131 file_size.d = fio->FileLength();
132 fio->Fseek(0, FILEIO_SEEK_SET);
134 if(check_file_extension(file_path, _T(".d88")) || check_file_extension(file_path, _T(".d77")) || check_file_extension(file_path, _T(".1dd"))) {
137 for(int i = 0; i < bank; i++) {
138 fio->Fseek(offset + 0x1c, SEEK_SET);
139 offset += fio->FgetUint32_LE();
141 fio->Fseek(offset + 0x1c, FILEIO_SEEK_SET);
142 file_size.d = fio->FgetUint32_LE();
143 fio->Fseek(offset, FILEIO_SEEK_SET);
144 fio->Fread(buffer, file_size.d, 1);
146 if(check_file_extension(file_path, _T(".1dd"))) {
148 media_type = MEDIA_TYPE_2DD;
150 inserted = changed = true;
151 // trim_required = true;
153 // fix sector number from big endian to little endian
154 for(int trkside = 0; trkside < 164; trkside++) {
156 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
158 if(!IS_VALID_TRACK(offset.d)) {
161 uint8* t = buffer + offset.d;
162 pair sector_num, data_size;
163 sector_num.read_2bytes_le_from(t + 4);
164 bool is_be = (sector_num.b.l == 0 && sector_num.b.h >= 4);
166 sector_num.read_2bytes_be_from(t + 4);
167 sector_num.write_2bytes_le_to(t + 4);
169 for(int i = 0; i < sector_num.sd; i++) {
171 sector_num.write_2bytes_le_to(t + 4);
173 data_size.read_2bytes_le_from(t + 14);
174 t += data_size.sd + 0x10;
177 } else if(check_file_extension(file_path, _T(".td0"))) {
180 inserted = changed = teledisk_to_d88(fio);
181 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
183 // failed to convert the disk image
185 } else if(check_file_extension(file_path, _T(".imd"))) {
188 inserted = changed = imagedisk_to_d88(fio);
189 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
191 // failed to convert the disk image
193 } else if(check_file_extension(file_path, _T(".dsk"))) {
196 inserted = changed = cpdread_to_d88(fio);
197 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
199 // failed to convert the disk image
201 } else if(check_file_extension(file_path, _T(".2d")) && file_size.d == 40 * 2 * 16 * 256) {
202 // 2d image for SHARP X1 series
203 inserted = changed = is_solid_image = solid_to_d88(fio, MEDIA_TYPE_2D, 40, 2, 16, 256, true);
204 } else if(check_file_extension(file_path, _T(".img")) && file_size.d == 70 * 1 * 16 * 256) {
205 // img image for SONY SMC-70/777 series
206 inserted = changed = is_solid_image = solid_to_d88(fio, MEDIA_TYPE_2DD, 70, 1, 16, 256, true);
207 } else if(check_file_extension(file_path, _T(".sf7")) && file_size.d == 40 * 1 * 16 * 256) {
208 // sf7 image for SEGA SC-3000 + SF-7000
209 inserted = changed = is_solid_image = solid_to_d88(fio, MEDIA_TYPE_2D, 40, 1, 16, 256, true);
212 // check solid image file format
213 bool is_fdi_tmp = check_file_extension(file_path, _T(".fdi"));
214 for(int i = 0;; i++) {
215 const fd_format_t *p = &fd_formats[i];
219 int len = p->ncyl * p->nside * p->nsec * p->size;
220 // 4096 bytes: FDI header ???
221 if(file_size.d == len + (is_fdi_tmp ? 4096 : 0)) {
222 fio->Fseek(0, FILEIO_SEEK_SET);
225 fio->Fread(fdi_header, 4096, 1);
229 int nside = p->nside;
232 #if defined(SUPPORT_MEDIA_TYPE_1DD)
233 if(type == MEDIA_TYPE_2D && nside == 2 && p->mfm) {
234 type = MEDIA_TYPE_2DD;
238 #elif defined(_ANY2D88)
239 if(open_as_1dd && type == MEDIA_TYPE_2D && nside == 2 && p->mfm) {
240 type = MEDIA_TYPE_2DD;
244 if(open_as_256 && (size == 512 || size == 1024)) {
249 // if(solid_to_d88(fio, p->type, p->ncyl, p->nside, p->nsec, p->size, p->mfm)) {
250 if(solid_to_d88(fio, type, ncyl, nside, nsec, size, p->mfm)) {
251 inserted = changed = is_solid_image = true;
257 if(fio->IsOpened()) {
263 // check loaded image
266 if(media_type == MEDIA_TYPE_UNK) {
267 if((media_type = buffer[0x1b]) == MEDIA_TYPE_2HD) {
268 // check 1.2MB or 1.44MB
269 for(int trkside = 0; trkside < 164; trkside++) {
271 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
273 if(!IS_VALID_TRACK(offset.d)) {
277 uint8 *t = buffer + offset.d;
278 pair sector_num, data_size;
279 sector_num.read_2bytes_le_from(t + 4);
280 data_size.read_2bytes_le_from(t + 14);
282 if(sector_num.sd >= 18 && data_size.sd == 512) {
283 media_type = MEDIA_TYPE_144;
290 // fix write protect flag
291 if(buffer[0x1a] != 0) {
293 write_protected = true;
296 // get crc32 for midification check
297 crc32 = getcrc32(buffer, file_size.d);
299 // check special disk image
300 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
301 // FIXME: ugly patch for FM-7 Gambler Jiko Chuushin Ha, DEATH FORCE and Psy-O-Blade
302 if(media_type == MEDIA_TYPE_2D) {
304 pair offset, sector_num, data_size;
305 offset.read_4bytes_le_from(buffer + 0x20);
306 if(IS_VALID_TRACK(offset.d)) {
307 // check the sector (c,h,r,n) = (0,0,7,1) or (0,0,f7,2)
308 uint8* t = buffer + offset.d;
309 sector_num.read_2bytes_le_from(t + 4);
310 for(int i = 0; i < sector_num.sd; i++) {
311 data_size.read_2bytes_le_from(t + 14);
312 if(is_special_disk == 0) {
313 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 7 && t[3] == 1) {
314 static const uint8 gambler[] = {0xb7, 0xde, 0xad, 0xdc, 0xdd, 0xcc, 0xde, 0xd7, 0xb1, 0x20, 0xbc, 0xde, 0xba, 0xc1, 0xad, 0xb3, 0xbc, 0xdd, 0xca};
315 if(memcmp((void *)(t + 0x30), gambler, sizeof(gambler)) == 0) {
316 is_special_disk = SPECIAL_DISK_FM7_GAMBLER;
319 } else if(data_size.sd == 0x200 && t[0] == 0 && t[1] == 0 && t[2] == 0xf7 && t[3] == 2) {
320 //"DEATHFORCE/77AV" + $f7*17 + $00 + $00
321 static const uint8 deathforce[] ={
322 0x44, 0x45, 0x41, 0x54, 0x48, 0x46, 0x4f, 0x52,
323 0x43, 0x45, 0x2f, 0x37, 0x37, 0x41, 0x56, 0xf7,
324 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
325 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
328 if(memcmp((void *)(t + 0x10), deathforce, sizeof(deathforce)) == 0) {
329 is_special_disk = SPECIAL_DISK_FM7_DEATHFORCE;
332 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 1 && t[3] == 1) {
333 //$03 + $2D + "PSY-O-BLADE Copyright 1988 by T&E SOFT Inc." + $B6 + $FD + $05
334 static const uint8 psyoblade_ipl1[] ={
335 0x03, 0x2d, 0x50, 0x53, 0x59, 0xa5, 0x4f, 0xa5,
336 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20, 0x20, 0x20,
337 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
338 0x74, 0x20, 0x31, 0x39, 0x38, 0x38, 0x20, 0x62,
339 0x79, 0x20, 0x54, 0x26, 0x45, 0x20, 0x53, 0x4f,
340 0x46, 0x54, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0xb6,
344 static const uint8 psyoblade_disk_1[] ={
345 0xc3, 0x00, 0x01, 0x00, 0x1a, 0x50, 0x86, 0xff,
346 0xb7, 0xfd, 0x10, 0xb7, 0xfd, 0x0f, 0x30, 0x8c,
347 0x0e, 0x8d, 0x35, 0x30, 0x8c, 0x14, 0x8d, 0x30,
348 0x30, 0x8c, 0x14, 0x8d, 0x2b, 0x20, 0xfe, 0x0a,
350 //$00 + $00 + $03 + $14 + "PSY-O-BLADE DISK" + $B6 + $FD + $05
351 static const uint8 psyoblade_disk_2[] ={
352 0x00, 0x00, 0x03, 0x14, 0x50, 0x53, 0x59, 0xa5,
353 0x4f, 0xa5, 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20,
354 0x20, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20
356 if(memcmp((void *)(t + 0x58), psyoblade_ipl1, sizeof(psyoblade_ipl1)) == 0) {
357 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
359 } else if(memcmp((void *)(t + 0x10), psyoblade_disk_1, sizeof(psyoblade_disk_1)) == 0) {
360 if(memcmp((void *)(t + 0x40), psyoblade_disk_2, sizeof(psyoblade_disk_2)) == 0) {
361 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
367 t += data_size.sd + 0x10;
371 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
372 // FIXME: ugly patch for X1turbo ALPHA and X1 Batten Tanuki
373 if(media_type == MEDIA_TYPE_2D) {
376 offset.read_4bytes_le_from(buffer + 0x20);
377 if(IS_VALID_TRACK(offset.d)) {
378 // check first sector
379 static const uint8 batten[] = {0xca, 0xde, 0xaf, 0xc3, 0xdd, 0x20, 0xc0, 0xc7, 0xb7};
380 uint8 *t = buffer + offset.d;
381 #if defined(_X1TURBO) || defined(_X1TURBOZ)
382 // if(strncmp((char *)(t + 0x11), "turbo ALPHA", 11) == 0) {
383 // is_special_disk = SPECIAL_DISK_X1TURBO_ALPHA;
386 if(memcmp((void *)(t + 0x11), batten, sizeof(batten)) == 0) {
387 is_special_disk = SPECIAL_DISK_X1_BATTEN;
401 trim_required = false;
403 buffer[0x1a] = write_protected ? 0x10 : 0; // mey be changed
405 if(/*!write_protected &&*/ file_size.d && getcrc32(buffer, file_size.d) != crc32) {
407 FILEIO* fio = new FILEIO();
408 int pre_size = 0, post_size = 0;
409 uint8 *pre_buffer = NULL, *post_buffer = NULL;
411 // is this d88 format ?
412 if(check_file_extension(dest_path, _T(".d88")) || check_file_extension(dest_path, _T(".d77")) || check_file_extension(dest_path, _T(".1dd"))) {
413 if(fio->Fopen(dest_path, FILEIO_READ_BINARY)) {
414 fio->Fseek(0, FILEIO_SEEK_END);
415 uint32 total_size = fio->Ftell(), offset = 0;
416 for(int i = 0; i < file_bank; i++) {
417 fio->Fseek(offset + 0x1c, SEEK_SET);
418 offset += fio->FgetUint32_LE();
420 if((pre_size = offset) > 0) {
421 pre_buffer = (uint8 *)malloc(pre_size);
422 fio->Fseek(0, FILEIO_SEEK_SET);
423 fio->Fread(pre_buffer, pre_size, 1);
425 fio->Fseek(offset + 0x1c, SEEK_SET);
426 offset += fio->FgetUint32_LE();
427 if((post_size = total_size - offset) > 0) {
428 post_buffer = (uint8 *)malloc(post_size);
429 fio->Fseek(offset, FILEIO_SEEK_SET);
430 fio->Fread(post_buffer, post_size, 1);
436 // is this solid image and was physical formatted ?
438 bool formatted = false;
441 for(int trkside = 0; trkside < 164; trkside++) {
443 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
445 if(!IS_VALID_TRACK(offset.d)) {
448 if(solid_nside == 1 && (trkside & 1) == 1) {
453 uint8* t = buffer + offset.d;
454 pair sector_num, data_size;
455 sector_num.read_2bytes_le_from(t + 4);
457 if(sector_num.sd != solid_nsec) {
460 for(int i = 0; i < sector_num.sd; i++) {
461 data_size.read_2bytes_le_from(t + 14);
462 if(data_size.sd != solid_size) {
465 if(t[6] != (solid_mfm ? 0 : 0x40)) {
468 t += data_size.sd + 0x10;
471 if(tracks != (solid_ncyl * solid_nside)) {
475 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), orig_path);
476 is_solid_image = false;
480 if((FILEIO::IsFileExists(dest_path) && FILEIO::IsFileProtected(dest_path)) || !fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
481 _TCHAR tmp_path[_MAX_PATH];
482 my_stprintf_s(tmp_path, _MAX_PATH, _T("temporary_saved_floppy_disk_#%d.d88"), drive_num);
483 fio->Fopen(local_path(tmp_path), FILEIO_WRITE_BINARY);
485 if(fio->IsOpened()) {
487 fio->Fwrite(pre_buffer, pre_size, 1);
491 fio->Fwrite(fdi_header, 4096, 1);
493 for(int trkside = 0; trkside < 164; trkside++) {
495 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
497 if(!IS_VALID_TRACK(offset.d)) {
500 uint8* t = buffer + offset.d;
501 pair sector_num, data_size;
502 sector_num.read_2bytes_le_from(t + 4);
504 for(int i = 0; i < sector_num.sd; i++) {
505 data_size.read_2bytes_le_from(t + 14);
506 fio->Fwrite(t + 0x10, data_size.sd, 1);
507 t += data_size.sd + 0x10;
511 fio->Fwrite(buffer, file_size.d, 1);
514 fio->Fwrite(post_buffer, post_size, 1);
528 inserted = write_protected = false;
530 sector_size.sd = sector_num.sd = 0;
535 void DISK::save_as_d88(const _TCHAR* file_path)
538 FILEIO* fio = new FILEIO();
539 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
541 memcpy(tmp_buffer, buffer + 0x20, 4 * 82);
542 for(int trk = 0; trk < 82; trk++) {
543 memcpy(buffer + 0x20 + (trk * 2 + 0) * 4, tmp_buffer + trk * 4, 4);
544 memset(buffer + 0x20 + (trk * 2 + 1) * 4, 0, 4);
546 buffer[0x1b] = MEDIA_TYPE_2DD;
548 fio->Fwrite(buffer, file_size.d, 1);
556 bool DISK::get_track(int trk, int side)
558 sector_size.sd = sector_num.sd = 0;
559 invalid_format = false;
562 // disk not inserted or invalid media type
563 if(!(inserted && check_media_type())) {
568 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
569 if(!(0 <= trkside && trkside < 164)) {
576 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
578 if(!IS_VALID_TRACK(offset.d)) {
583 sector = buffer + offset.d;
584 sector_num.read_2bytes_le_from(sector + 4);
586 data_size.read_2bytes_le_from(sector + 14);
588 // create each sector position in track
590 if(sector_num.sd == 0) {
591 track_mfm = drive_mfm;
594 for(int i = 0; i < sector_num.sd; i++) {
595 data_size.read_2bytes_le_from(t + 14);
596 // t[6]: 0x00 = double-density, 0x40 = single-density
601 t += data_size.sd + 0x10;
604 int sync_size = track_mfm ? 12 : 6;
605 int am_size = track_mfm ? 3 : 0;
606 int gap0_size = track_mfm ? 80 : 40;
607 int gap1_size = track_mfm ? 50 : 26;
608 int gap2_size = track_mfm ? 22 : 11;
609 // int gap3_size = 0, gap4_size;
613 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
615 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
616 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
617 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
619 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
620 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
621 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
625 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
626 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
627 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
629 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
630 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
631 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
636 int total = 0, valid_sector_num = 0;
638 for(int i = 0; i < sector_num.sd; i++) {
639 data_size.read_2bytes_le_from(t + 14);
640 sync_position[i] = total; // for invalid format case
641 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
642 if(data_size.sd > 0) {
643 total += sync_size + (am_size + 1);
644 total += data_size.sd + 2;
647 //if(t[2] != i + 1) {
650 t += data_size.sd + 0x10;
652 total += sync_size + (am_size + 1); // sync in preamble
655 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (valid_sector_num + 1);
657 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
659 if(gap3_size < 8 || gap4_size < 8) {
660 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + valid_sector_num + 1);
661 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
663 //printf("GAP3=%d GAP4=%d\n", gap3_size, gap4_size);
664 if(gap3_size < 8 || gap4_size < 8) {
665 gap0_size = gap1_size = gap3_size = gap4_size = 8;
666 //gap0_size = gap1_size = gap3_size = gap4_size = 32;
667 invalid_format = true;
670 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
673 total -= sync_size + (am_size + 1);
674 for(int i = 0; i < sector_num.sd; i++) {
675 sync_position[i] *= get_track_size() - preamble_size - gap4_size;
676 sync_position[i] /= total;
680 total = preamble_size;
681 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
683 for(int i = 0; i < sector_num.sd; i++) {
684 data_size.read_2bytes_le_from(t + 14);
686 total = preamble_size + sync_position[i];
688 sync_position[i] = total;
690 am1_position[i] = total;
691 total += am_size + 1;
692 id_position[i] = total;
693 total += (4 + 2) + gap2_size;
694 if(data_size.sd > 0) {
695 total += sync_size + (am_size + 1);
696 data_position[i] = total;
697 total += data_size.sd + 2;
700 data_position[i] = total; // FIXME
702 t += data_size.sd + 0x10;
707 bool DISK::make_track(int trk, int side)
709 int track_size = get_track_size();
711 if(!get_track(trk, side)) {
712 // create a dummy track
713 for(int i = 0; i < track_size; i++) {
720 int sync_size = track_mfm ? 12 : 6;
721 int am_size = track_mfm ? 3 : 0;
722 int gap2_size = track_mfm ? 22 : 11;
723 uint8 gap_data = track_mfm ? 0x4e : 0xff;
726 memset(track, gap_data, track_size);
727 int q = sync_position[array_length(sync_position) - 1];
730 for(int i = 0; i < sync_size; i++) {
734 for(int i = 0; i < am_size; i++) {
742 for(int i = 0; i < sector_num.sd; i++) {
744 data_size.read_2bytes_le_from(t + 14);
745 int p = sync_position[i];
748 for(int j = 0; j < sync_size; j++) {
749 if(p < track_size) track[p++] = 0x00;
752 for(int j = 0; j < am_size; j++) {
753 if(p < track_size) track[p++] = 0xa1;
755 if(p < track_size) track[p++] = 0xfe;
757 if(p < track_size) track[p++] = t[0];
758 if(p < track_size) track[p++] = t[1];
759 if(p < track_size) track[p++] = t[2];
760 if(p < track_size) track[p++] = t[3];
762 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
763 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
764 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
765 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
766 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
767 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
769 for(int j = 0; j < gap2_size; j++) {
770 if(p < track_size) track[p++] = gap_data;
773 if(data_size.sd > 0) {
775 for(int j = 0; j < sync_size; j++) {
776 if(p < track_size) track[p++] = 0x00;
779 for(int j = 0; j < am_size; j++) {
780 if(p < track_size) track[p++] = 0xa1;
782 if(p < track_size) track[p++] = (t[7] != 0) ? 0xf8 : 0xfb;
785 for(int j = 0; j < data_size.sd; j++) {
786 if(p < track_size) track[p++] = t[0x10 + j];
787 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0x10 + j]]);
789 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
790 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
792 t += data_size.sd + 0x10;
797 bool DISK::get_sector(int trk, int side, int index)
799 sector_size.sd = sector_num.sd = 0;
802 // disk not inserted or invalid media type
803 if(!(inserted && check_media_type())) {
808 if(trk == -1 && side == -1) {
812 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
813 if(!(0 <= trkside && trkside < 164)) {
817 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
819 if(!IS_VALID_TRACK(offset.d)) {
824 uint8* t = buffer + offset.d;
825 sector_num.read_2bytes_le_from(t + 4);
827 if(index >= sector_num.sd) {
832 for(int i = 0; i < index; i++) {
834 data_size.read_2bytes_le_from(t + 14);
835 t += data_size.sd + 0x10;
841 void DISK::set_sector_info(uint8 *t)
849 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
850 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
851 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
852 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
853 id[4] = (crc >> 8) & 0xff;
854 id[5] = (crc >> 0) & 0xff;
855 // http://www,gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
856 // t[6]: 0x00 = double-density, 0x40 = single-density
857 // t[7]: 0x00 = normal, 0x10 = deleted mark
858 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
860 deleted = (t[7] != 0);
862 // if(ignore_crc()) {
863 // addr_crc_error = false;
864 // data_crc_error = false;
866 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
867 data_crc_error = ((t[8] & 0xf0) == 0xb0);
870 sector_size.read_2bytes_le_from(t + 14);
873 void DISK::set_deleted(bool value)
876 uint8 *t = sector - 0x10;
877 t[7] = value ? 0x10 : 0;
878 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
879 t[8] = (t[8] & 0x0f) | t[7];
885 void DISK::set_data_crc_error(bool value)
888 uint8 *t = sector - 0x10;
889 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
891 data_crc_error = value;
894 void DISK::set_data_mark_missing()
897 uint8 *t = sector - 0x10;
898 t[8] = (t[8] & 0x0f) | 0xf0;
902 //addr_crc_error = false;
903 data_crc_error = false;
906 bool DISK::format_track(int trk, int side)
908 // disk not inserted or invalid media type
909 if(!(inserted && check_media_type())) {
914 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
915 if(!(0 <= trkside && trkside < 164)) {
919 // create new empty track
922 trim_required = false;
924 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
926 offset.d = DISK_BUFFER_SIZE;
927 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
929 trim_required = true;
931 track_mfm = drive_mfm;
936 void DISK::insert_sector(uint8 c, uint8 h, uint8 r, uint8 n, bool deleted, bool data_crc_error, uint8 fill_data, int length)
938 uint8* t = buffer + DISK_BUFFER_SIZE;
941 for(int i = 0; i < (sector_num.sd - 1); i++) {
942 t[4] = sector_num.b.l;
943 t[5] = sector_num.b.h;
945 data_size.read_2bytes_le_from(t + 14);
946 t += data_size.sd + 0x10;
952 t[4] = sector_num.b.l;
953 t[5] = sector_num.b.h;
954 t[6] = track_mfm ? 0 : 0x40;
955 t[7] = deleted ? 0x10 : 0;
956 t[8] = data_crc_error ? 0xb0 : t[7];
957 t[14] = (length >> 0) & 0xff;
958 t[15] = (length >> 8) & 0xff;
959 memset(t + 16, fill_data, length);
964 void DISK::sync_buffer()
968 trim_required = false;
972 void DISK::trim_buffer()
974 int max_tracks = 164;
975 uint32 dest_offset = 0x2b0;
978 memset(tmp_buffer, 0, sizeof(tmp_buffer));
979 memcpy(tmp_buffer, buffer, 0x20);
982 for(int trkside = 0; trkside < 164; trkside++) {
984 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
985 if(src_trk_offset.d != 0) {
987 if(src_trk_offset.d < 0x2b0) {
988 max_tracks = (src_trk_offset.d - 0x20) >> 2;
991 if(src_trk_offset.d != 0x2b0) {
992 max_tracks = (src_trk_offset.d - 0x20) >> 2;
993 if(max_tracks > 164) {
994 dest_offset = 0x20 + max_tracks * 4);
1003 for(int trkside = 0; trkside < max_tracks; trkside++) {
1004 pair src_trk_offset;
1005 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1007 pair dest_trk_offset;
1008 dest_trk_offset.d = 0;
1010 if(IS_VALID_TRACK(src_trk_offset.d)) {
1011 uint8* t = buffer + src_trk_offset.d;
1012 pair sector_num, data_size;
1013 sector_num.read_2bytes_le_from(t + 4);
1014 if(sector_num.sd != 0) {
1015 dest_trk_offset.d = dest_offset;
1016 for(int i = 0; i < sector_num.sd; i++) {
1017 data_size.read_2bytes_le_from(t + 14);
1018 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
1019 dest_offset += data_size.sd + 0x10;
1020 t += data_size.sd + 0x10;
1024 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
1028 file_size.d = dest_offset;
1029 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
1031 memset(buffer, 0, sizeof(buffer));
1032 memcpy(buffer, tmp_buffer, min(sizeof(buffer), file_size.d));
1037 if(drive_rpm != 0) {
1039 } else if(inserted) {
1040 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
1042 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
1046 int DISK::get_track_size()
1049 //#if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1050 // if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
1051 //return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3500;
1055 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : track_mfm ? 6250 : 3100;
1057 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
1061 double DISK::get_usec_per_track()
1063 return 1000000.0 / (get_rpm() / 60.0);
1066 double DISK::get_usec_per_bytes(int bytes)
1068 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1071 int DISK::get_bytes_per_usec(double usec)
1073 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1076 bool DISK::check_media_type()
1078 switch(drive_type) {
1080 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1081 defined(_FM77AV20) || defined(_FM77AV20EX)
1082 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1084 return (media_type == MEDIA_TYPE_2D);
1086 case DRIVE_TYPE_2DD:
1087 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1088 case DRIVE_TYPE_2HD:
1089 return (media_type == MEDIA_TYPE_2HD);
1090 case DRIVE_TYPE_144:
1091 return (media_type == MEDIA_TYPE_144);
1092 case DRIVE_TYPE_UNK:
1093 return true; // always okay
1100 #define COPYBUFFER(src, size) { \
1101 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1104 memcpy(buffer + file_size.d, (src), (size)); \
1105 file_size.d += (size); \
1120 uint8 dens, del, stat;
1125 // teledisk image decoder
1128 this teledisk image decoder is based on:
1130 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1131 LZSS coded by Haruhiko OKUMURA
1132 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1133 Edited and translated to English by Kenji RIKITAKE
1137 #define STRING_BUFFER_SIZE 4096
1138 #define LOOKAHEAD_BUFFER_SIZE 60
1140 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1141 #define TABLE_SIZE (N_CHAR * 2 - 1)
1142 #define ROOT_POSITION (TABLE_SIZE - 1)
1143 #define MAX_FREQ 0x8000
1145 static uint8 td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1146 static uint16 td_ptr;
1147 static uint16 td_bufcnt, td_bufndx, td_bufpos;
1148 static uint16 td_ibufcnt, td_ibufndx;
1149 static uint8 td_inbuf[512];
1150 static uint16 td_freq[TABLE_SIZE + 1];
1151 static short td_prnt[TABLE_SIZE + N_CHAR];
1152 static short td_son[TABLE_SIZE];
1153 static uint16 td_getbuf;
1154 static uint8 td_getlen;
1156 static const uint8 td_d_code[256] = {
1157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1160 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1161 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1162 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1163 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1164 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1165 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1166 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1167 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1168 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1169 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1170 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1171 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1172 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1174 static const uint8 td_d_len[256] = {
1175 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1176 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1177 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1178 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1179 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1180 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1181 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1182 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1183 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1184 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1185 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1186 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1187 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1188 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1189 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1190 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1193 static int td_next_word(FILEIO* fio)
1195 if(td_ibufndx >= td_ibufcnt) {
1196 td_ibufndx = td_ibufcnt = 0;
1197 memset(td_inbuf, 0, 512);
1198 for(int i = 0; i < 512; i++) {
1199 int d = fio->Fgetc();
1210 while(td_getlen <= 8) {
1211 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1217 static int td_get_bit(FILEIO* fio)
1219 if(td_next_word(fio) < 0) {
1222 short i = td_getbuf;
1225 return (i < 0) ? 1 : 0;
1228 static int td_get_byte(FILEIO* fio)
1230 if(td_next_word(fio) != 0) {
1233 uint16 i = td_getbuf;
1240 static void td_start_huff()
1243 for(i = 0; i < N_CHAR; i++) {
1245 td_son[i] = i + TABLE_SIZE;
1246 td_prnt[i + TABLE_SIZE] = i;
1249 while(j <= ROOT_POSITION) {
1250 td_freq[j] = td_freq[i] + td_freq[i + 1];
1252 td_prnt[i] = td_prnt[i + 1] = j;
1255 td_freq[TABLE_SIZE] = 0xffff;
1256 td_prnt[ROOT_POSITION] = 0;
1259 static void td_reconst()
1263 for(i = 0; i < TABLE_SIZE; i++) {
1264 if(td_son[i] >= TABLE_SIZE) {
1265 td_freq[j] = (td_freq[i] + 1) / 2;
1266 td_son[j] = td_son[i];
1270 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1272 f = td_freq[j] = td_freq[i] + td_freq[k];
1273 for(k = j - 1; f < td_freq[k]; k--);
1276 memmove(&td_freq[k + 1], &td_freq[k], l);
1278 memmove(&td_son[k + 1], &td_son[k], l);
1281 for(i = 0; i < TABLE_SIZE; i++) {
1282 if((k = td_son[i]) >= TABLE_SIZE) {
1285 td_prnt[k] = td_prnt[k + 1] = i;
1290 static void td_update(int c)
1293 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1296 c = td_prnt[c + TABLE_SIZE];
1299 if(k > td_freq[l = c + 1]) {
1300 while(k > td_freq[++l]);
1302 td_freq[c] = td_freq[l];
1306 if(i < TABLE_SIZE) {
1312 if(j < TABLE_SIZE) {
1319 while((c = td_prnt[c]) != 0);
1322 static short td_decode_char(FILEIO* fio)
1325 uint16 c = td_son[ROOT_POSITION];
1326 while(c < TABLE_SIZE) {
1327 if((ret = td_get_bit(fio)) < 0) {
1338 static short td_decode_position(FILEIO* fio)
1342 if((bit = td_get_byte(fio)) < 0) {
1346 c = (uint16)td_d_code[i] << 6;
1347 j = td_d_len[i] - 2;
1349 if((bit = td_get_bit(fio)) < 0) {
1354 return (c | i & 0x3f);
1357 static void td_init_decode()
1359 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1362 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1363 td_text_buf[i] = ' ';
1365 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1368 static int td_decode(FILEIO* fio, uint8 *buf, int len)
1372 for(count = 0; count < len;) {
1373 if(td_bufcnt == 0) {
1374 if((c = td_decode_char(fio)) < 0) {
1378 *(buf++) = (uint8)c;
1379 td_text_buf[td_ptr++] = (uint8)c;
1380 td_ptr &= (STRING_BUFFER_SIZE - 1);
1383 if((pos = td_decode_position(fio)) < 0) {
1386 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1387 td_bufcnt = c - 255 + THRESHOLD;
1391 while(td_bufndx < td_bufcnt && count < len) {
1392 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1393 *(buf++) = (uint8)c;
1395 td_text_buf[td_ptr++] = (uint8)c;
1396 td_ptr &= (STRING_BUFFER_SIZE - 1);
1399 if(td_bufndx >= td_bufcnt) {
1400 td_bufndx = td_bufcnt = 0;
1427 uint8 nsec, trk, head;
1436 bool DISK::teledisk_to_d88(FILEIO *fio)
1443 bool temporary = false;
1445 // check teledisk header
1446 fio->Fseek(0, FILEIO_SEEK_SET);
1447 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1448 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1449 // this image is compressed
1450 // decompress to the temporary file
1451 FILEIO* fio_tmp = new FILEIO();
1452 if(!fio_tmp->Fopen(local_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1459 if((rd = td_decode(fio, obuf, 512)) > 0) {
1460 fio_tmp->Fwrite(obuf, rd, 1);
1468 // reopen the temporary file
1470 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1473 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1474 // this image is not compressed
1478 if(hdr.flag & 0x80) {
1480 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1481 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1484 // create d88 header
1488 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1489 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1490 d88_hdr.protect = 0; // non-protected
1493 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1496 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1497 fio->Fread(&trk, sizeof(td_trk_t), 1);
1498 while(trk.nsec != 0xff) {
1499 d88_hdr.trkptr[trkcnt++] = trkptr;
1500 if(hdr.sides == 1) {
1504 // read sectors in this track
1505 for(int i = 0; i < trk.nsec; i++) {
1506 uint8 buf[2048], dst[2048];
1507 memset(buf, 0, sizeof(buf));
1508 memset(dst, 0, sizeof(dst));
1510 // read sector header
1511 fio->Fread(&sct, sizeof(td_sct_t), 1);
1513 // create d88 sector header
1514 memset(&d88_sct, 0, sizeof(d88_sct_t));
1519 d88_sct.nsec = trk.nsec;
1520 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1521 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1522 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1523 d88_sct.size = secsize[sct.n & 3];
1525 // create sector image
1526 if(sct.ctrl & 0x30) {
1527 d88_sct.stat = 0xf0; // data mark missing
1530 // read sector source
1531 int len = fio->Fgetc();
1532 len += fio->Fgetc() * 256 - 1;
1533 int flag = fio->Fgetc(), d = 0;
1534 fio->Fread(buf, len, 1);
1538 memcpy(dst, buf, len);
1539 } else if(flag == 1) {
1541 len2.read_2bytes_le_from(buf);
1546 } else if(flag == 2) {
1547 for(int s = 0; s < len;) {
1548 int type = buf[s++];
1549 int len2 = buf[s++];
1552 dst[d++] = buf[s++];
1554 } else if(type < 5) {
1560 for(int j = 0; j < n; j++) {
1564 for(int j = 0; j < n; j++) {
1569 break; // unknown type
1573 break; // unknown flag
1578 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1579 COPYBUFFER(dst, d88_sct.size);
1580 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1583 fio->Fread(&trk, sizeof(td_trk_t), 1);
1585 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1586 d88_hdr.size = trkptr;
1587 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1590 FILEIO::RemoveFile(_T("teledisk.$$$"));
1595 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
1597 bool DISK::imagedisk_to_d88(FILEIO *fio)
1599 int size = fio->FileLength();
1600 fio->Fseek(0, FILEIO_SEEK_SET);
1601 fio->Fread(tmp_buffer, size, 1);
1603 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
1608 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
1615 // create d88 header
1619 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1620 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
1621 d88_hdr.protect = 0; // non-protected
1624 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1627 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1632 // check track header
1633 uint8 mode = tmp_buffer[pos++];
1634 uint8 track = tmp_buffer[pos++];
1635 uint8 head = tmp_buffer[pos++];
1636 uint8 sector_count = tmp_buffer[pos++];
1637 uint8 ssize = tmp_buffer[pos++];
1639 if(sector_count == 0) {
1645 uint32 actual_size = ssize < 7 ? 128 << ssize : 8192;
1648 const uint8 *snum = &tmp_buffer[pos];
1649 pos += sector_count;
1650 const uint8 *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
1652 pos += sector_count;
1653 const uint8 *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
1655 pos += sector_count;
1659 int trkside = track * 2 + (head & 1);
1661 if(trkcnt < trkside) {
1664 d88_hdr.trkptr[trkside] = trkptr;
1666 if(img_mode == -1) {
1667 img_mode = mode & 3;
1670 // read sectors in this track
1671 for(int i = 0; i < sector_count; i++) {
1672 // create d88 sector header
1673 uint8 stype = tmp_buffer[pos++];
1674 memset(&d88_sct, 0, sizeof(d88_sct_t));
1675 d88_sct.c = tnum ? tnum[i] : track;
1676 d88_sct.h = hnum ? hnum[i] : head;
1677 d88_sct.r = snum[i];
1679 d88_sct.nsec = sector_count;
1680 d88_sct.dens = (mode < 3) ? 0x40 : 0;
1682 if(stype == 0 || stype > 8) {
1683 d88_sct.stat = 0xf0; // data mark missing
1686 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
1687 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
1688 d88_sct.size = actual_size;
1690 // create sector image
1691 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
1692 memset(dst, tmp_buffer[pos++], actual_size);
1694 memcpy(dst, &tmp_buffer[pos], actual_size);
1695 pos += d88_sct.size;
1701 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1702 COPYBUFFER(dst, d88_sct.size);
1703 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1707 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1708 d88_hdr.size = trkptr;
1709 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1713 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
1715 #define DSK_FORMAT_HEADER "MV - CPC"
1716 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
1719 struct track_header {
1720 uint8 headertag[13];
1727 uint8 sector_size_code;
1728 uint8 number_of_sector;
1732 struct sector_header {
1736 uint8 sector_size_code;
1737 uint8 fdc_status_reg1;
1738 uint8 fdc_status_reg2;
1743 bool DISK::cpdread_to_d88(FILEIO *fio)
1745 bool extendformat = false;
1746 int image_size = fio->FileLength();
1748 fio->Fseek(0, FILEIO_SEEK_SET);
1749 fio->Fread(tmp_buffer, image_size, 1);
1751 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
1752 extendformat = true;
1753 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
1754 extendformat = false;
1759 int heads = tmp_buffer[0x31];
1764 int tracks = tmp_buffer[0x30];
1765 int track_offsets[84 * 2];
1766 bool track_offsets_error = false;
1768 int cnt = 0, tmp = 0x100;
1769 for(int i = 0; i < tracks * heads; i++) {
1770 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1773 track_offsets[cnt] = tmp;
1774 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
1778 int cnt = 0, tmp = 0x100;
1779 for(int i = 0; i < tracks * heads; i++) {
1780 int length = tmp_buffer[0x34 + i] << 8;
1782 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1785 track_offsets[cnt] = tmp;
1788 track_offsets[cnt] = image_size;
1793 if(track_offsets_error) {
1794 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
1795 // so I modified this code to search "Track-Info" at the top of track information block
1796 int cnt = 0, tmp = 0x100;
1797 for(int i = 0; i < tracks * heads; i++) {
1799 for(; tmp < image_size; tmp += 0x10) {
1800 if(found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0)) {
1805 track_offsets[cnt] = tmp;
1808 track_offsets[cnt] = image_size;
1814 // create d88 header
1818 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1819 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
1820 d88_hdr.protect = 0; // non-protected
1823 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1826 int total = 0, trkptr = sizeof(d88_hdr_t);
1828 for(int track = 0; track < tracks; track++) {
1829 for(int side = 0; side < heads; side++) {
1830 if(track_offsets[(track << 1) + side] >= image_size) {
1833 if((track << 1) + side < 164) {
1834 d88_hdr.trkptr[(track << 1) + side] = trkptr;
1838 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
1839 int pos = track_offsets[(track << 1) + side] + 0x100;
1840 for(int j = 0; j < tr.number_of_sector; j++) {
1841 sector_header sector;
1842 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
1844 // create d88 sector header
1845 memset(&d88_sct, 0, sizeof(d88_sct_t));
1846 d88_sct.c = sector.track;
1847 d88_sct.h = sector.side;
1848 d88_sct.r = sector.sector_id;
1849 d88_sct.n = sector.sector_size_code;
1850 d88_sct.nsec = tr.number_of_sector;
1852 d88_sct.size = sector.data_length;
1853 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
1855 d88_sct.size = 128 << tr.sector_size_code;
1856 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
1858 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
1859 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
1862 if((track << 1) + side < 164) {
1863 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1864 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
1865 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1867 total += d88_sct.size;
1870 pos += sector.data_length;
1872 pos += 128 << tr.sector_size_code;
1877 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
1878 d88_hdr.size = trkptr;
1879 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1883 // solid image decoder
1885 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
1891 solid_nside = nside;
1896 // create d88 header
1900 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1901 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
1902 d88_hdr.protect = 0; // non-protected
1905 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1908 for(int i = 0; i < 8; i++) {
1909 if(size == (128 << i)) {
1916 int trkptr = sizeof(d88_hdr_t);
1918 for(int c = 0; c < ncyl; c++) {
1919 for(int h = 0; h < nside; h++) {
1920 d88_hdr.trkptr[t++] = trkptr;
1925 // read sectors in this track
1926 for(int s = 0; s < nsec; s++) {
1927 // create d88 sector header
1928 memset(&d88_sct, 0, sizeof(d88_sct_t));
1933 d88_sct.nsec = nsec;
1937 d88_sct.size = size;
1939 // create sector image
1941 memset(dst, 0xe5, sizeof(dst));
1942 fio->Fread(dst, size, 1);
1945 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1946 COPYBUFFER(dst, size);
1947 trkptr += sizeof(d88_sct_t) + size;
1951 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
1952 d88_hdr.size = trkptr;
1953 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1957 #define STATE_VERSION 11
1959 void DISK::save_state(FILEIO* state_fio)
1961 state_fio->FputUint32(STATE_VERSION);
1963 state_fio->Fwrite(buffer, sizeof(buffer), 1);
1964 state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
1965 state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
1966 state_fio->FputUint32(file_size.d);
1967 state_fio->FputInt32(file_bank);
1968 state_fio->FputUint32(crc32);
1969 state_fio->FputBool(trim_required);
1970 state_fio->FputBool(is_1dd_image);
1971 state_fio->FputBool(is_solid_image);
1972 state_fio->FputBool(is_fdi_image);
1973 state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
1974 state_fio->FputInt32(solid_ncyl);
1975 state_fio->FputInt32(solid_nside);
1976 state_fio->FputInt32(solid_nsec);
1977 state_fio->FputInt32(solid_size);
1978 state_fio->FputBool(solid_mfm);
1979 state_fio->FputBool(inserted);
1980 state_fio->FputBool(ejected);
1981 state_fio->FputBool(write_protected);
1982 state_fio->FputBool(changed);
1983 state_fio->FputUint8(media_type);
1984 state_fio->FputInt32(is_special_disk);
1985 state_fio->Fwrite(track, sizeof(track), 1);
1986 state_fio->FputInt32(sector_num.sd);
1987 state_fio->FputBool(track_mfm);
1988 state_fio->FputBool(invalid_format);
1989 //state_fio->FputBool(no_skew);
1990 state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
1991 state_fio->Fwrite(am1_position, sizeof(am1_position), 1);
1992 state_fio->Fwrite(id_position, sizeof(id_position), 1);
1993 state_fio->Fwrite(data_position, sizeof(data_position), 1);
1994 state_fio->FputInt32(gap3_size);
1995 state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
1996 state_fio->FputInt32(sector_size.sd);
1997 state_fio->Fwrite(id, sizeof(id), 1);
1998 state_fio->FputUint8(density);
1999 state_fio->FputBool(deleted);
2000 state_fio->FputBool(addr_crc_error);
2001 state_fio->FputBool(data_crc_error);
2002 state_fio->FputUint8(drive_type);
2003 state_fio->FputInt32(drive_rpm);
2004 state_fio->FputBool(drive_mfm);
2007 bool DISK::load_state(FILEIO* state_fio)
2009 if(state_fio->FgetUint32() != STATE_VERSION) {
2012 state_fio->Fread(buffer, sizeof(buffer), 1);
2013 state_fio->Fread(orig_path, sizeof(orig_path), 1);
2014 state_fio->Fread(dest_path, sizeof(dest_path), 1);
2015 file_size.d = state_fio->FgetUint32();
2016 file_bank = state_fio->FgetInt32();
2017 crc32 = state_fio->FgetUint32();
2018 trim_required = state_fio->FgetBool();
2019 is_1dd_image = state_fio->FgetBool();
2020 is_solid_image = state_fio->FgetBool();
2021 is_fdi_image = state_fio->FgetBool();
2022 state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
2023 solid_ncyl = state_fio->FgetInt32();
2024 solid_nside = state_fio->FgetInt32();
2025 solid_nsec = state_fio->FgetInt32();
2026 solid_size = state_fio->FgetInt32();
2027 solid_mfm = state_fio->FgetBool();
2028 inserted = state_fio->FgetBool();
2029 ejected = state_fio->FgetBool();
2030 write_protected = state_fio->FgetBool();
2031 changed = state_fio->FgetBool();
2032 media_type = state_fio->FgetUint8();
2033 is_special_disk = state_fio->FgetInt32();
2034 state_fio->Fread(track, sizeof(track), 1);
2035 sector_num.sd = state_fio->FgetInt32();
2036 track_mfm = state_fio->FgetBool();
2037 invalid_format = state_fio->FgetBool();
2038 //no_skew = state_fio->FgetBool();
2039 state_fio->Fread(sync_position, sizeof(sync_position), 1);
2040 state_fio->Fread(am1_position, sizeof(am1_position), 1);
2041 state_fio->Fread(id_position, sizeof(id_position), 1);
2042 state_fio->Fread(data_position, sizeof(data_position), 1);
2043 gap3_size = state_fio->FgetInt32();
2044 int offset = state_fio->FgetInt32();
2045 sector = (offset != -1) ? buffer + offset : NULL;
2046 sector_size.sd = state_fio->FgetInt32();
2047 state_fio->Fread(id, sizeof(id), 1);
2048 density = state_fio->FgetUint8();
2049 deleted = state_fio->FgetBool();
2050 addr_crc_error = state_fio->FgetBool();
2051 data_crc_error = state_fio->FgetBool();
2052 drive_type = state_fio->FgetUint8();
2053 drive_rpm = state_fio->FgetInt32();
2054 drive_mfm = state_fio->FgetBool();