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(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 7 && t[3] == 1) {
313 static const uint8 gambler[] = {0xb7, 0xde, 0xad, 0xdc, 0xdd, 0xcc, 0xde, 0xd7, 0xb1, 0x20, 0xbc, 0xde, 0xba, 0xc1, 0xad, 0xb3, 0xbc, 0xdd, 0xca};
314 if(memcmp((void *)(t + 0x30), gambler, sizeof(gambler)) == 0) {
315 is_special_disk = SPECIAL_DISK_FM7_GAMBLER;
318 } else if(data_size.sd == 0x200 && t[0] == 0 && t[1] == 0 && t[2] == 0xf7 && t[3] == 2) {
319 //"DEATHFORCE/77AV" + $f7*17 + $00 + $00
320 static const uint8 deathforce[] ={
321 0x44, 0x45, 0x41, 0x54, 0x48, 0x46, 0x4f, 0x52,
322 0x43, 0x45, 0x2f, 0x37, 0x37, 0x41, 0x56, 0xf7,
323 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
324 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
327 if(memcmp((void *)(t + 0x10), deathforce, sizeof(deathforce)) == 0) {
328 is_special_disk = SPECIAL_DISK_FM7_DEATHFORCE;
331 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 1 && t[3] == 1) {
332 //$03 + $2D + "PSY-O-BLADE Copyright 1988 by T&E SOFT Inc" + $B6 + $FD + $05
333 static const uint8 psyoblade_ipl1[] ={
334 0x03, 0x2d, 0x50, 0x53, 0x59, 0xa5, 0x4f, 0xa5,
335 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20, 0x20, 0x20,
336 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
337 0x74, 0x20, 0x31, 0x39, 0x38, 0x38, 0x20, 0x62,
338 0x79, 0x20, 0x54, 0x26, 0x45, 0x20, 0x53, 0x4f,
339 0x46, 0x54, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0xb6,
343 static const uint8 psyoblade_disk_1[] ={
344 0xc3, 0x00, 0x01, 0x00, 0x1a, 0x50, 0x86, 0xff,
345 0xb7, 0xfd, 0x10, 0xb7, 0xfd, 0x0f, 0x30, 0x8c,
346 0x0e, 0x8d, 0x35, 0x30, 0x8c, 0x14, 0x8d, 0x30,
347 0x30, 0x8c, 0x14, 0x8d, 0x2b, 0x20, 0xfe, 0x0a,
349 //$00 + $00 + $03 + $14 + "PSY-O-BLADE DISK" + $B6 + $FD + $05
350 static const uint8 psyoblade_disk_2[] ={
351 0x00, 0x00, 0x03, 0x14, 0x50, 0x53, 0x59, 0xa5,
352 0x4f, 0xa5, 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20,
353 0x20, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20
355 if(memcmp((void *)(t + 0x58), psyoblade_ipl1, sizeof(psyoblade_ipl1)) == 0) {
356 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
358 } else if(memcmp((void *)(t + 0x10), psyoblade_disk_1, sizeof(psyoblade_disk_1)) == 0) {
359 if(memcmp((void *)(t + 0x40), psyoblade_disk_2, sizeof(psyoblade_disk_2)) == 0) {
360 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
365 t += data_size.sd + 0x10;
369 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
370 // FIXME: ugly patch for X1turbo ALPHA and X1 Batten Tanuki
371 if(media_type == MEDIA_TYPE_2D) {
374 offset.read_4bytes_le_from(buffer + 0x20);
375 if(IS_VALID_TRACK(offset.d)) {
376 // check first sector
377 static const uint8 batten[] = {0xca, 0xde, 0xaf, 0xc3, 0xdd, 0x20, 0xc0, 0xc7, 0xb7};
378 uint8 *t = buffer + offset.d;
379 #if defined(_X1TURBO) || defined(_X1TURBOZ)
380 // if(strncmp((char *)(t + 0x11), "turbo ALPHA", 11) == 0) {
381 // is_special_disk = SPECIAL_DISK_X1TURBO_ALPHA;
384 if(memcmp((void *)(t + 0x11), batten, sizeof(batten)) == 0) {
385 is_special_disk = SPECIAL_DISK_X1_BATTEN;
399 trim_required = false;
401 buffer[0x1a] = write_protected ? 0x10 : 0; // mey be changed
403 if(/*!write_protected &&*/ file_size.d && getcrc32(buffer, file_size.d) != crc32) {
405 FILEIO* fio = new FILEIO();
406 int pre_size = 0, post_size = 0;
407 uint8 *pre_buffer = NULL, *post_buffer = NULL;
409 // is this d88 format ?
410 if(check_file_extension(dest_path, _T(".d88")) || check_file_extension(dest_path, _T(".d77")) || check_file_extension(dest_path, _T(".1dd"))) {
411 if(fio->Fopen(dest_path, FILEIO_READ_BINARY)) {
412 fio->Fseek(0, FILEIO_SEEK_END);
413 uint32 total_size = fio->Ftell(), offset = 0;
414 for(int i = 0; i < file_bank; i++) {
415 fio->Fseek(offset + 0x1c, SEEK_SET);
416 offset += fio->FgetUint32_LE();
418 if((pre_size = offset) > 0) {
419 pre_buffer = (uint8 *)malloc(pre_size);
420 fio->Fseek(0, FILEIO_SEEK_SET);
421 fio->Fread(pre_buffer, pre_size, 1);
423 fio->Fseek(offset + 0x1c, SEEK_SET);
424 offset += fio->FgetUint32_LE();
425 if((post_size = total_size - offset) > 0) {
426 post_buffer = (uint8 *)malloc(post_size);
427 fio->Fseek(offset, FILEIO_SEEK_SET);
428 fio->Fread(post_buffer, post_size, 1);
434 // is this solid image and was physical formatted ?
436 bool formatted = false;
439 for(int trkside = 0; trkside < 164; trkside++) {
441 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
443 if(!IS_VALID_TRACK(offset.d)) {
446 if(solid_nside == 1 && (trkside & 1) == 1) {
451 uint8* t = buffer + offset.d;
452 pair sector_num, data_size;
453 sector_num.read_2bytes_le_from(t + 4);
455 if(sector_num.sd != solid_nsec) {
458 for(int i = 0; i < sector_num.sd; i++) {
459 data_size.read_2bytes_le_from(t + 14);
460 if(data_size.sd != solid_size) {
463 if(t[6] != (solid_mfm ? 0 : 0x40)) {
466 t += data_size.sd + 0x10;
469 if(tracks != (solid_ncyl * solid_nside)) {
473 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), orig_path);
474 is_solid_image = false;
478 if((FILEIO::IsFileExists(dest_path) && FILEIO::IsFileProtected(dest_path)) || !fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
479 _TCHAR tmp_path[_MAX_PATH];
480 my_stprintf_s(tmp_path, _MAX_PATH, _T("temporary_saved_floppy_disk_#%d.d88"), drive_num);
481 fio->Fopen(local_path(tmp_path), FILEIO_WRITE_BINARY);
483 if(fio->IsOpened()) {
485 fio->Fwrite(pre_buffer, pre_size, 1);
489 fio->Fwrite(fdi_header, 4096, 1);
491 for(int trkside = 0; trkside < 164; trkside++) {
493 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
495 if(!IS_VALID_TRACK(offset.d)) {
498 uint8* t = buffer + offset.d;
499 pair sector_num, data_size;
500 sector_num.read_2bytes_le_from(t + 4);
502 for(int i = 0; i < sector_num.sd; i++) {
503 data_size.read_2bytes_le_from(t + 14);
504 fio->Fwrite(t + 0x10, data_size.sd, 1);
505 t += data_size.sd + 0x10;
509 fio->Fwrite(buffer, file_size.d, 1);
512 fio->Fwrite(post_buffer, post_size, 1);
526 inserted = write_protected = false;
528 sector_size.sd = sector_num.sd = 0;
533 void DISK::save_as_d88(const _TCHAR* file_path)
536 FILEIO* fio = new FILEIO();
537 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
539 memcpy(tmp_buffer, buffer + 0x20, 4 * 82);
540 for(int trk = 0; trk < 82; trk++) {
541 memcpy(buffer + 0x20 + (trk * 2 + 0) * 4, tmp_buffer + trk * 4, 4);
542 memset(buffer + 0x20 + (trk * 2 + 1) * 4, 0, 4);
544 buffer[0x1b] = MEDIA_TYPE_2DD;
546 fio->Fwrite(buffer, file_size.d, 1);
554 bool DISK::get_track(int trk, int side)
556 sector_size.sd = sector_num.sd = 0;
557 invalid_format = false;
560 // disk not inserted or invalid media type
561 if(!(inserted && check_media_type())) {
566 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
567 if(!(0 <= trkside && trkside < 164)) {
574 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
576 if(!IS_VALID_TRACK(offset.d)) {
581 sector = buffer + offset.d;
582 sector_num.read_2bytes_le_from(sector + 4);
584 data_size.read_2bytes_le_from(sector + 14);
586 // create each sector position in track
588 if(sector_num.sd == 0) {
589 track_mfm = drive_mfm;
592 for(int i = 0; i < sector_num.sd; i++) {
593 data_size.read_2bytes_le_from(t + 14);
594 // t[6]: 0x00 = double-density, 0x40 = single-density
599 t += data_size.sd + 0x10;
602 int sync_size = track_mfm ? 12 : 6;
603 int am_size = track_mfm ? 3 : 0;
604 int gap0_size = track_mfm ? 80 : 40;
605 int gap1_size = track_mfm ? 50 : 26;
606 int gap2_size = track_mfm ? 22 : 11;
607 // int gap3_size = 0, gap4_size;
611 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
613 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
614 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
615 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
617 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
618 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
619 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
623 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
624 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
625 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
627 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
628 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
629 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
634 int total = 0, valid_sector_num = 0;
636 for(int i = 0; i < sector_num.sd; i++) {
637 data_size.read_2bytes_le_from(t + 14);
638 sync_position[i] = total; // for invalid format case
639 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
640 if(data_size.sd > 0) {
641 total += sync_size + (am_size + 1);
642 total += data_size.sd + 2;
645 //if(t[2] != i + 1) {
648 t += data_size.sd + 0x10;
650 total += sync_size + (am_size + 1); // sync in preamble
653 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (valid_sector_num + 1);
655 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
657 if(gap3_size < 8 || gap4_size < 8) {
658 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + valid_sector_num + 1);
659 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * valid_sector_num;
661 if(gap3_size < 8 || gap4_size < 8) {
662 gap0_size = gap1_size = gap3_size = gap4_size = 8;
663 invalid_format = true;
665 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
668 total -= sync_size + (am_size + 1);
669 for(int i = 0; i < sector_num.sd; i++) {
670 sync_position[i] *= get_track_size() - preamble_size - gap4_size;
671 sync_position[i] /= total;
675 total = preamble_size;
676 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
678 for(int i = 0; i < sector_num.sd; i++) {
679 data_size.read_2bytes_le_from(t + 14);
681 total = preamble_size + sync_position[i];
683 sync_position[i] = total;
685 am1_position[i] = total;
686 total += am_size + 1;
687 id_position[i] = total;
688 total += (4 + 2) + gap2_size;
689 if(data_size.sd > 0) {
690 total += sync_size + (am_size + 1);
691 data_position[i] = total;
692 total += data_size.sd + 2;
695 data_position[i] = total; // FIXME
697 t += data_size.sd + 0x10;
702 bool DISK::make_track(int trk, int side)
704 int track_size = get_track_size();
706 if(!get_track(trk, side)) {
707 // create a dummy track
708 for(int i = 0; i < track_size; i++) {
715 int sync_size = track_mfm ? 12 : 6;
716 int am_size = track_mfm ? 3 : 0;
717 int gap2_size = track_mfm ? 22 : 11;
718 uint8 gap_data = track_mfm ? 0x4e : 0xff;
721 memset(track, gap_data, track_size);
722 int q = sync_position[array_length(sync_position) - 1];
725 for(int i = 0; i < sync_size; i++) {
729 for(int i = 0; i < am_size; i++) {
737 for(int i = 0; i < sector_num.sd; i++) {
739 data_size.read_2bytes_le_from(t + 14);
740 int p = sync_position[i];
743 for(int j = 0; j < sync_size; j++) {
744 if(p < track_size) track[p++] = 0x00;
747 for(int j = 0; j < am_size; j++) {
748 if(p < track_size) track[p++] = 0xa1;
750 if(p < track_size) track[p++] = 0xfe;
752 if(p < track_size) track[p++] = t[0];
753 if(p < track_size) track[p++] = t[1];
754 if(p < track_size) track[p++] = t[2];
755 if(p < track_size) track[p++] = t[3];
757 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
758 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
759 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
760 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
761 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
762 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
764 for(int j = 0; j < gap2_size; j++) {
765 if(p < track_size) track[p++] = gap_data;
768 if(data_size.sd > 0) {
770 for(int j = 0; j < sync_size; j++) {
771 if(p < track_size) track[p++] = 0x00;
774 for(int j = 0; j < am_size; j++) {
775 if(p < track_size) track[p++] = 0xa1;
777 if(p < track_size) track[p++] = (t[7] != 0) ? 0xf8 : 0xfb;
780 for(int j = 0; j < data_size.sd; j++) {
781 if(p < track_size) track[p++] = t[0x10 + j];
782 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0x10 + j]]);
784 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
785 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
787 t += data_size.sd + 0x10;
792 bool DISK::get_sector(int trk, int side, int index)
794 sector_size.sd = sector_num.sd = 0;
797 // disk not inserted or invalid media type
798 if(!(inserted && check_media_type())) {
803 if(trk == -1 && side == -1) {
807 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
808 if(!(0 <= trkside && trkside < 164)) {
812 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
814 if(!IS_VALID_TRACK(offset.d)) {
819 uint8* t = buffer + offset.d;
820 sector_num.read_2bytes_le_from(t + 4);
822 if(index >= sector_num.sd) {
827 for(int i = 0; i < index; i++) {
829 data_size.read_2bytes_le_from(t + 14);
830 t += data_size.sd + 0x10;
836 void DISK::set_sector_info(uint8 *t)
844 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
845 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
846 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
847 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
848 id[4] = (crc >> 8) & 0xff;
849 id[5] = (crc >> 0) & 0xff;
850 // http://www,gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
851 // t[6]: 0x00 = double-density, 0x40 = single-density
852 // t[7]: 0x00 = normal, 0x10 = deleted mark
853 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
855 deleted = (t[7] != 0);
857 // if(ignore_crc()) {
858 // addr_crc_error = false;
859 // data_crc_error = false;
861 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
862 data_crc_error = ((t[8] & 0xf0) == 0xb0);
865 sector_size.read_2bytes_le_from(t + 14);
868 void DISK::set_deleted(bool value)
871 uint8 *t = sector - 0x10;
872 t[7] = value ? 0x10 : 0;
873 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
874 t[8] = (t[8] & 0x0f) | t[7];
880 void DISK::set_data_crc_error(bool value)
883 uint8 *t = sector - 0x10;
884 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
886 data_crc_error = value;
889 void DISK::set_data_mark_missing()
892 uint8 *t = sector - 0x10;
893 t[8] = (t[8] & 0x0f) | 0xf0;
897 //addr_crc_error = false;
898 data_crc_error = false;
901 bool DISK::format_track(int trk, int side)
903 // disk not inserted or invalid media type
904 if(!(inserted && check_media_type())) {
909 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
910 if(!(0 <= trkside && trkside < 164)) {
914 // create new empty track
917 trim_required = false;
919 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
921 offset.d = DISK_BUFFER_SIZE;
922 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
924 trim_required = true;
926 track_mfm = drive_mfm;
931 void DISK::insert_sector(uint8 c, uint8 h, uint8 r, uint8 n, bool deleted, bool data_crc_error, uint8 fill_data, int length)
933 uint8* t = buffer + DISK_BUFFER_SIZE;
936 for(int i = 0; i < (sector_num.sd - 1); i++) {
937 t[4] = sector_num.b.l;
938 t[5] = sector_num.b.h;
940 data_size.read_2bytes_le_from(t + 14);
941 t += data_size.sd + 0x10;
947 t[4] = sector_num.b.l;
948 t[5] = sector_num.b.h;
949 t[6] = track_mfm ? 0 : 0x40;
950 t[7] = deleted ? 0x10 : 0;
951 t[8] = data_crc_error ? 0xb0 : t[7];
952 t[14] = (length >> 0) & 0xff;
953 t[15] = (length >> 8) & 0xff;
954 memset(t + 16, fill_data, length);
959 void DISK::sync_buffer()
963 trim_required = false;
967 void DISK::trim_buffer()
969 int max_tracks = 164;
970 uint32 dest_offset = 0x2b0;
973 memset(tmp_buffer, 0, sizeof(tmp_buffer));
974 memcpy(tmp_buffer, buffer, 0x20);
977 for(int trkside = 0; trkside < 164; trkside++) {
979 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
980 if(src_trk_offset.d != 0) {
982 if(src_trk_offset.d < 0x2b0) {
983 max_tracks = (src_trk_offset.d - 0x20) >> 2;
986 if(src_trk_offset.d != 0x2b0) {
987 max_tracks = (src_trk_offset.d - 0x20) >> 2;
988 if(max_tracks > 164) {
989 dest_offset = 0x20 + max_tracks * 4);
998 for(int trkside = 0; trkside < max_tracks; trkside++) {
1000 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1002 pair dest_trk_offset;
1003 dest_trk_offset.d = 0;
1005 if(IS_VALID_TRACK(src_trk_offset.d)) {
1006 uint8* t = buffer + src_trk_offset.d;
1007 pair sector_num, data_size;
1008 sector_num.read_2bytes_le_from(t + 4);
1009 if(sector_num.sd != 0) {
1010 dest_trk_offset.d = dest_offset;
1011 for(int i = 0; i < sector_num.sd; i++) {
1012 data_size.read_2bytes_le_from(t + 14);
1013 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
1014 dest_offset += data_size.sd + 0x10;
1015 t += data_size.sd + 0x10;
1019 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
1023 file_size.d = dest_offset;
1024 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
1026 memset(buffer, 0, sizeof(buffer));
1027 // memcpy(buffer, tmp_buffer, file_size.d);
1028 memcpy(buffer, tmp_buffer, min(sizeof(buffer), file_size.d));
1029 //memcpy(buffer, tmp_buffer, (file_size.d > sizeof(buffer)) ? sizeof(buffer) : file_size.d);
1034 if(drive_rpm != 0) {
1036 } else if(inserted) {
1037 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
1039 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
1043 int DISK::get_track_size()
1046 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1047 if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
1048 //return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3500;
1052 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : track_mfm ? 6250 : 3100;
1054 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
1058 double DISK::get_usec_per_track()
1060 #if defined(_FM77AV_VARIANTS)
1061 if(is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE) {
1062 return 1000000.0 / (get_rpm() / 60.0 * 2.2);
1065 return 1000000.0 / (get_rpm() / 60.0);
1068 double DISK::get_usec_per_bytes(int bytes)
1070 #if defined(_FM77AV_VARIANTS)
1071 if(is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE) {
1072 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0) * 2.2) * bytes;
1075 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1078 int DISK::get_bytes_per_usec(double usec)
1080 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1083 bool DISK::check_media_type()
1085 switch(drive_type) {
1087 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1088 defined(_FM77AV20) || defined(_FM77AV20EX)
1089 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1091 return (media_type == MEDIA_TYPE_2D);
1093 case DRIVE_TYPE_2DD:
1094 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1095 case DRIVE_TYPE_2HD:
1096 return (media_type == MEDIA_TYPE_2HD);
1097 case DRIVE_TYPE_144:
1098 return (media_type == MEDIA_TYPE_144);
1099 case DRIVE_TYPE_UNK:
1100 return true; // always okay
1107 #define COPYBUFFER(src, size) { \
1108 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1111 memcpy(buffer + file_size.d, (src), (size)); \
1112 file_size.d += (size); \
1127 uint8 dens, del, stat;
1132 // teledisk image decoder
1135 this teledisk image decoder is based on:
1137 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1138 LZSS coded by Haruhiko OKUMURA
1139 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1140 Edited and translated to English by Kenji RIKITAKE
1144 #define STRING_BUFFER_SIZE 4096
1145 #define LOOKAHEAD_BUFFER_SIZE 60
1147 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1148 #define TABLE_SIZE (N_CHAR * 2 - 1)
1149 #define ROOT_POSITION (TABLE_SIZE - 1)
1150 #define MAX_FREQ 0x8000
1152 static uint8 td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1153 static uint16 td_ptr;
1154 static uint16 td_bufcnt, td_bufndx, td_bufpos;
1155 static uint16 td_ibufcnt, td_ibufndx;
1156 static uint8 td_inbuf[512];
1157 static uint16 td_freq[TABLE_SIZE + 1];
1158 static short td_prnt[TABLE_SIZE + N_CHAR];
1159 static short td_son[TABLE_SIZE];
1160 static uint16 td_getbuf;
1161 static uint8 td_getlen;
1163 static const uint8 td_d_code[256] = {
1164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1166 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1167 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1168 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1169 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1170 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1171 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1172 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1173 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1174 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1175 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1176 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1177 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1178 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1179 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1181 static const uint8 td_d_len[256] = {
1182 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1183 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1184 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1185 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1186 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1187 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1188 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1189 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1190 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1191 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1192 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1193 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1194 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1195 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1196 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1197 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1200 static int td_next_word(FILEIO* fio)
1202 if(td_ibufndx >= td_ibufcnt) {
1203 td_ibufndx = td_ibufcnt = 0;
1204 memset(td_inbuf, 0, 512);
1205 for(int i = 0; i < 512; i++) {
1206 int d = fio->Fgetc();
1217 while(td_getlen <= 8) {
1218 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1224 static int td_get_bit(FILEIO* fio)
1226 if(td_next_word(fio) < 0) {
1229 short i = td_getbuf;
1232 return (i < 0) ? 1 : 0;
1235 static int td_get_byte(FILEIO* fio)
1237 if(td_next_word(fio) != 0) {
1240 uint16 i = td_getbuf;
1247 static void td_start_huff()
1250 for(i = 0; i < N_CHAR; i++) {
1252 td_son[i] = i + TABLE_SIZE;
1253 td_prnt[i + TABLE_SIZE] = i;
1256 while(j <= ROOT_POSITION) {
1257 td_freq[j] = td_freq[i] + td_freq[i + 1];
1259 td_prnt[i] = td_prnt[i + 1] = j;
1262 td_freq[TABLE_SIZE] = 0xffff;
1263 td_prnt[ROOT_POSITION] = 0;
1266 static void td_reconst()
1270 for(i = 0; i < TABLE_SIZE; i++) {
1271 if(td_son[i] >= TABLE_SIZE) {
1272 td_freq[j] = (td_freq[i] + 1) / 2;
1273 td_son[j] = td_son[i];
1277 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1279 f = td_freq[j] = td_freq[i] + td_freq[k];
1280 for(k = j - 1; f < td_freq[k]; k--);
1283 memmove(&td_freq[k + 1], &td_freq[k], l);
1285 memmove(&td_son[k + 1], &td_son[k], l);
1288 for(i = 0; i < TABLE_SIZE; i++) {
1289 if((k = td_son[i]) >= TABLE_SIZE) {
1292 td_prnt[k] = td_prnt[k + 1] = i;
1297 static void td_update(int c)
1300 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1303 c = td_prnt[c + TABLE_SIZE];
1306 if(k > td_freq[l = c + 1]) {
1307 while(k > td_freq[++l]);
1309 td_freq[c] = td_freq[l];
1313 if(i < TABLE_SIZE) {
1319 if(j < TABLE_SIZE) {
1326 while((c = td_prnt[c]) != 0);
1329 static short td_decode_char(FILEIO* fio)
1332 uint16 c = td_son[ROOT_POSITION];
1333 while(c < TABLE_SIZE) {
1334 if((ret = td_get_bit(fio)) < 0) {
1345 static short td_decode_position(FILEIO* fio)
1349 if((bit = td_get_byte(fio)) < 0) {
1353 c = (uint16)td_d_code[i] << 6;
1354 j = td_d_len[i] - 2;
1356 if((bit = td_get_bit(fio)) < 0) {
1361 return (c | i & 0x3f);
1364 static void td_init_decode()
1366 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1369 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1370 td_text_buf[i] = ' ';
1372 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1375 static int td_decode(FILEIO* fio, uint8 *buf, int len)
1379 for(count = 0; count < len;) {
1380 if(td_bufcnt == 0) {
1381 if((c = td_decode_char(fio)) < 0) {
1385 *(buf++) = (uint8)c;
1386 td_text_buf[td_ptr++] = (uint8)c;
1387 td_ptr &= (STRING_BUFFER_SIZE - 1);
1390 if((pos = td_decode_position(fio)) < 0) {
1393 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1394 td_bufcnt = c - 255 + THRESHOLD;
1398 while(td_bufndx < td_bufcnt && count < len) {
1399 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1400 *(buf++) = (uint8)c;
1402 td_text_buf[td_ptr++] = (uint8)c;
1403 td_ptr &= (STRING_BUFFER_SIZE - 1);
1406 if(td_bufndx >= td_bufcnt) {
1407 td_bufndx = td_bufcnt = 0;
1434 uint8 nsec, trk, head;
1443 bool DISK::teledisk_to_d88(FILEIO *fio)
1450 bool temporary = false;
1452 // check teledisk header
1453 fio->Fseek(0, FILEIO_SEEK_SET);
1454 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1455 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1456 // this image is compressed
1457 // decompress to the temporary file
1458 FILEIO* fio_tmp = new FILEIO();
1459 if(!fio_tmp->Fopen(local_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1466 if((rd = td_decode(fio, obuf, 512)) > 0) {
1467 fio_tmp->Fwrite(obuf, rd, 1);
1475 // reopen the temporary file
1477 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1480 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1481 // this image is not compressed
1485 if(hdr.flag & 0x80) {
1487 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1488 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1491 // create d88 header
1495 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1496 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1497 d88_hdr.protect = 0; // non-protected
1500 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1503 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1504 fio->Fread(&trk, sizeof(td_trk_t), 1);
1505 while(trk.nsec != 0xff) {
1506 d88_hdr.trkptr[trkcnt++] = trkptr;
1507 if(hdr.sides == 1) {
1511 // read sectors in this track
1512 for(int i = 0; i < trk.nsec; i++) {
1513 uint8 buf[2048], dst[2048];
1514 memset(buf, 0, sizeof(buf));
1515 memset(dst, 0, sizeof(dst));
1517 // read sector header
1518 fio->Fread(&sct, sizeof(td_sct_t), 1);
1520 // create d88 sector header
1521 memset(&d88_sct, 0, sizeof(d88_sct_t));
1526 d88_sct.nsec = trk.nsec;
1527 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1528 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1529 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1530 d88_sct.size = secsize[sct.n & 3];
1532 // create sector image
1533 if(sct.ctrl & 0x30) {
1534 d88_sct.stat = 0xf0; // data mark missing
1537 // read sector source
1538 int len = fio->Fgetc();
1539 len += fio->Fgetc() * 256 - 1;
1540 int flag = fio->Fgetc(), d = 0;
1541 fio->Fread(buf, len, 1);
1545 memcpy(dst, buf, len);
1546 } else if(flag == 1) {
1548 len2.read_2bytes_le_from(buf);
1553 } else if(flag == 2) {
1554 for(int s = 0; s < len;) {
1555 int type = buf[s++];
1556 int len2 = buf[s++];
1559 dst[d++] = buf[s++];
1561 } else if(type < 5) {
1567 for(int j = 0; j < n; j++) {
1571 for(int j = 0; j < n; j++) {
1576 break; // unknown type
1580 break; // unknown flag
1585 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1586 COPYBUFFER(dst, d88_sct.size);
1587 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1590 fio->Fread(&trk, sizeof(td_trk_t), 1);
1592 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1593 d88_hdr.size = trkptr;
1594 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1597 FILEIO::RemoveFile(_T("teledisk.$$$"));
1602 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
1604 bool DISK::imagedisk_to_d88(FILEIO *fio)
1606 int size = fio->FileLength();
1607 fio->Fseek(0, FILEIO_SEEK_SET);
1608 fio->Fread(tmp_buffer, size, 1);
1610 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
1615 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
1622 // create d88 header
1626 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1627 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
1628 d88_hdr.protect = 0; // non-protected
1631 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1634 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1639 // check track header
1640 uint8 mode = tmp_buffer[pos++];
1641 uint8 track = tmp_buffer[pos++];
1642 uint8 head = tmp_buffer[pos++];
1643 uint8 sector_count = tmp_buffer[pos++];
1644 uint8 ssize = tmp_buffer[pos++];
1646 if(sector_count == 0) {
1652 uint32 actual_size = ssize < 7 ? 128 << ssize : 8192;
1655 const uint8 *snum = &tmp_buffer[pos];
1656 pos += sector_count;
1657 const uint8 *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
1659 pos += sector_count;
1660 const uint8 *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
1662 pos += sector_count;
1666 int trkside = track * 2 + (head & 1);
1668 if(trkcnt < trkside) {
1671 d88_hdr.trkptr[trkside] = trkptr;
1673 if(img_mode == -1) {
1674 img_mode = mode & 3;
1677 // read sectors in this track
1678 for(int i = 0; i < sector_count; i++) {
1679 // create d88 sector header
1680 uint8 stype = tmp_buffer[pos++];
1681 memset(&d88_sct, 0, sizeof(d88_sct_t));
1682 d88_sct.c = tnum ? tnum[i] : track;
1683 d88_sct.h = hnum ? hnum[i] : head;
1684 d88_sct.r = snum[i];
1686 d88_sct.nsec = sector_count;
1687 d88_sct.dens = (mode < 3) ? 0x40 : 0;
1689 if(stype == 0 || stype > 8) {
1690 d88_sct.stat = 0xf0; // data mark missing
1693 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
1694 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
1695 d88_sct.size = actual_size;
1697 // create sector image
1698 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
1699 memset(dst, tmp_buffer[pos++], actual_size);
1701 memcpy(dst, &tmp_buffer[pos], actual_size);
1702 pos += d88_sct.size;
1708 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1709 COPYBUFFER(dst, d88_sct.size);
1710 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1714 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1715 d88_hdr.size = trkptr;
1716 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1720 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
1722 #define DSK_FORMAT_HEADER "MV - CPC"
1723 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
1726 struct track_header {
1727 uint8 headertag[13];
1734 uint8 sector_size_code;
1735 uint8 number_of_sector;
1739 struct sector_header {
1743 uint8 sector_size_code;
1744 uint8 fdc_status_reg1;
1745 uint8 fdc_status_reg2;
1750 bool DISK::cpdread_to_d88(FILEIO *fio)
1752 bool extendformat = false;
1753 int image_size = fio->FileLength();
1755 fio->Fseek(0, FILEIO_SEEK_SET);
1756 fio->Fread(tmp_buffer, image_size, 1);
1758 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
1759 extendformat = true;
1760 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
1761 extendformat = false;
1766 int heads = tmp_buffer[0x31];
1771 int tracks = tmp_buffer[0x30];
1772 int track_offsets[84 * 2];
1773 bool track_offsets_error = false;
1775 int cnt = 0, tmp = 0x100;
1776 for(int i = 0; i < tracks * heads; i++) {
1777 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1780 track_offsets[cnt] = tmp;
1781 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
1785 int cnt = 0, tmp = 0x100;
1786 for(int i = 0; i < tracks * heads; i++) {
1787 int length = tmp_buffer[0x34 + i] << 8;
1789 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1792 track_offsets[cnt] = tmp;
1795 track_offsets[cnt] = image_size;
1800 if(track_offsets_error) {
1801 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
1802 // so I modified this code to search "Track-Info" at the top of track information block
1803 int cnt = 0, tmp = 0x100;
1804 for(int i = 0; i < tracks * heads; i++) {
1806 for(; tmp < image_size; tmp += 0x10) {
1807 if(found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0)) {
1812 track_offsets[cnt] = tmp;
1815 track_offsets[cnt] = image_size;
1821 // create d88 header
1825 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1826 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
1827 d88_hdr.protect = 0; // non-protected
1830 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1833 int total = 0, trkptr = sizeof(d88_hdr_t);
1835 for(int track = 0; track < tracks; track++) {
1836 for(int side = 0; side < heads; side++) {
1837 if(track_offsets[(track << 1) + side] >= image_size) {
1840 if((track << 1) + side < 164) {
1841 d88_hdr.trkptr[(track << 1) + side] = trkptr;
1845 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
1846 int pos = track_offsets[(track << 1) + side] + 0x100;
1847 for(int j = 0; j < tr.number_of_sector; j++) {
1848 sector_header sector;
1849 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
1851 // create d88 sector header
1852 memset(&d88_sct, 0, sizeof(d88_sct_t));
1853 d88_sct.c = sector.track;
1854 d88_sct.h = sector.side;
1855 d88_sct.r = sector.sector_id;
1856 d88_sct.n = sector.sector_size_code;
1857 d88_sct.nsec = tr.number_of_sector;
1859 d88_sct.size = sector.data_length;
1860 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
1862 d88_sct.size = 128 << tr.sector_size_code;
1863 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
1865 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
1866 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
1869 if((track << 1) + side < 164) {
1870 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1871 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
1872 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1874 total += d88_sct.size;
1877 pos += sector.data_length;
1879 pos += 128 << tr.sector_size_code;
1884 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
1885 d88_hdr.size = trkptr;
1886 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1890 // solid image decoder
1892 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
1898 solid_nside = nside;
1903 // create d88 header
1907 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1908 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
1909 d88_hdr.protect = 0; // non-protected
1912 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1915 for(int i = 0; i < 8; i++) {
1916 if(size == (128 << i)) {
1923 int trkptr = sizeof(d88_hdr_t);
1925 for(int c = 0; c < ncyl; c++) {
1926 for(int h = 0; h < nside; h++) {
1927 d88_hdr.trkptr[t++] = trkptr;
1932 // read sectors in this track
1933 for(int s = 0; s < nsec; s++) {
1934 // create d88 sector header
1935 memset(&d88_sct, 0, sizeof(d88_sct_t));
1940 d88_sct.nsec = nsec;
1944 d88_sct.size = size;
1946 // create sector image
1948 memset(dst, 0xe5, sizeof(dst));
1949 fio->Fread(dst, size, 1);
1952 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1953 COPYBUFFER(dst, size);
1954 trkptr += sizeof(d88_sct_t) + size;
1958 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
1959 d88_hdr.size = trkptr;
1960 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1964 #define STATE_VERSION 11
1966 void DISK::save_state(FILEIO* state_fio)
1968 state_fio->FputUint32(STATE_VERSION);
1970 state_fio->Fwrite(buffer, sizeof(buffer), 1);
1971 state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
1972 state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
1973 state_fio->FputUint32(file_size.d);
1974 state_fio->FputInt32(file_bank);
1975 state_fio->FputUint32(crc32);
1976 state_fio->FputBool(trim_required);
1977 state_fio->FputBool(is_1dd_image);
1978 state_fio->FputBool(is_solid_image);
1979 state_fio->FputBool(is_fdi_image);
1980 state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
1981 state_fio->FputInt32(solid_ncyl);
1982 state_fio->FputInt32(solid_nside);
1983 state_fio->FputInt32(solid_nsec);
1984 state_fio->FputInt32(solid_size);
1985 state_fio->FputBool(solid_mfm);
1986 state_fio->FputBool(inserted);
1987 state_fio->FputBool(ejected);
1988 state_fio->FputBool(write_protected);
1989 state_fio->FputBool(changed);
1990 state_fio->FputUint8(media_type);
1991 state_fio->FputInt32(is_special_disk);
1992 state_fio->Fwrite(track, sizeof(track), 1);
1993 state_fio->FputInt32(sector_num.sd);
1994 state_fio->FputBool(track_mfm);
1995 state_fio->FputBool(invalid_format);
1996 //state_fio->FputBool(no_skew);
1997 state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
1998 state_fio->Fwrite(am1_position, sizeof(am1_position), 1);
1999 state_fio->Fwrite(id_position, sizeof(id_position), 1);
2000 state_fio->Fwrite(data_position, sizeof(data_position), 1);
2001 state_fio->FputInt32(gap3_size);
2002 state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
2003 state_fio->FputInt32(sector_size.sd);
2004 state_fio->Fwrite(id, sizeof(id), 1);
2005 state_fio->FputUint8(density);
2006 state_fio->FputBool(deleted);
2007 state_fio->FputBool(addr_crc_error);
2008 state_fio->FputBool(data_crc_error);
2009 state_fio->FputUint8(drive_type);
2010 state_fio->FputInt32(drive_rpm);
2011 state_fio->FputBool(drive_mfm);
2014 bool DISK::load_state(FILEIO* state_fio)
2016 if(state_fio->FgetUint32() != STATE_VERSION) {
2019 state_fio->Fread(buffer, sizeof(buffer), 1);
2020 state_fio->Fread(orig_path, sizeof(orig_path), 1);
2021 state_fio->Fread(dest_path, sizeof(dest_path), 1);
2022 file_size.d = state_fio->FgetUint32();
2023 file_bank = state_fio->FgetInt32();
2024 crc32 = state_fio->FgetUint32();
2025 trim_required = state_fio->FgetBool();
2026 is_1dd_image = state_fio->FgetBool();
2027 is_solid_image = state_fio->FgetBool();
2028 is_fdi_image = state_fio->FgetBool();
2029 state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
2030 solid_ncyl = state_fio->FgetInt32();
2031 solid_nside = state_fio->FgetInt32();
2032 solid_nsec = state_fio->FgetInt32();
2033 solid_size = state_fio->FgetInt32();
2034 solid_mfm = state_fio->FgetBool();
2035 inserted = state_fio->FgetBool();
2036 ejected = state_fio->FgetBool();
2037 write_protected = state_fio->FgetBool();
2038 changed = state_fio->FgetBool();
2039 media_type = state_fio->FgetUint8();
2040 is_special_disk = state_fio->FgetInt32();
2041 state_fio->Fread(track, sizeof(track), 1);
2042 sector_num.sd = state_fio->FgetInt32();
2043 track_mfm = state_fio->FgetBool();
2044 invalid_format = state_fio->FgetBool();
2045 //no_skew = state_fio->FgetBool();
2046 state_fio->Fread(sync_position, sizeof(sync_position), 1);
2047 state_fio->Fread(am1_position, sizeof(am1_position), 1);
2048 state_fio->Fread(id_position, sizeof(id_position), 1);
2049 state_fio->Fread(data_position, sizeof(data_position), 1);
2050 gap3_size = state_fio->FgetInt32();
2051 int offset = state_fio->FgetInt32();
2052 sector = (offset != -1) ? buffer + offset : NULL;
2053 sector_size.sd = state_fio->FgetInt32();
2054 state_fio->Fread(id, sizeof(id), 1);
2055 density = state_fio->FgetUint8();
2056 deleted = state_fio->FgetBool();
2057 addr_crc_error = state_fio->FgetBool();
2058 data_crc_error = state_fio->FgetBool();
2059 drive_type = state_fio->FgetUint8();
2060 drive_rpm = state_fio->FgetInt32();
2061 drive_mfm = state_fio->FgetBool();