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 return 1000000.0 / (get_rpm() / 60.0);
1063 double DISK::get_usec_per_bytes(int bytes)
1065 #if defined(_FM77AV_VARIANTS)
1066 if(is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE) {
1067 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0) * 2.2) * bytes;
1070 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1073 int DISK::get_bytes_per_usec(double usec)
1075 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1078 bool DISK::check_media_type()
1080 switch(drive_type) {
1082 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1083 defined(_FM77AV20) || defined(_FM77AV20EX)
1084 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1086 return (media_type == MEDIA_TYPE_2D);
1088 case DRIVE_TYPE_2DD:
1089 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1090 case DRIVE_TYPE_2HD:
1091 return (media_type == MEDIA_TYPE_2HD);
1092 case DRIVE_TYPE_144:
1093 return (media_type == MEDIA_TYPE_144);
1094 case DRIVE_TYPE_UNK:
1095 return true; // always okay
1102 #define COPYBUFFER(src, size) { \
1103 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1106 memcpy(buffer + file_size.d, (src), (size)); \
1107 file_size.d += (size); \
1122 uint8 dens, del, stat;
1127 // teledisk image decoder
1130 this teledisk image decoder is based on:
1132 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1133 LZSS coded by Haruhiko OKUMURA
1134 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1135 Edited and translated to English by Kenji RIKITAKE
1139 #define STRING_BUFFER_SIZE 4096
1140 #define LOOKAHEAD_BUFFER_SIZE 60
1142 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1143 #define TABLE_SIZE (N_CHAR * 2 - 1)
1144 #define ROOT_POSITION (TABLE_SIZE - 1)
1145 #define MAX_FREQ 0x8000
1147 static uint8 td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1148 static uint16 td_ptr;
1149 static uint16 td_bufcnt, td_bufndx, td_bufpos;
1150 static uint16 td_ibufcnt, td_ibufndx;
1151 static uint8 td_inbuf[512];
1152 static uint16 td_freq[TABLE_SIZE + 1];
1153 static short td_prnt[TABLE_SIZE + N_CHAR];
1154 static short td_son[TABLE_SIZE];
1155 static uint16 td_getbuf;
1156 static uint8 td_getlen;
1158 static const uint8 td_d_code[256] = {
1159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1161 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1162 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1163 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1164 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1165 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1166 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1167 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1168 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1169 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1170 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1171 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1172 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1173 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1174 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1176 static const uint8 td_d_len[256] = {
1177 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1178 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1179 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1180 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1181 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
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 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1185 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1186 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1187 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1188 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1189 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1190 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1191 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1192 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1195 static int td_next_word(FILEIO* fio)
1197 if(td_ibufndx >= td_ibufcnt) {
1198 td_ibufndx = td_ibufcnt = 0;
1199 memset(td_inbuf, 0, 512);
1200 for(int i = 0; i < 512; i++) {
1201 int d = fio->Fgetc();
1212 while(td_getlen <= 8) {
1213 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1219 static int td_get_bit(FILEIO* fio)
1221 if(td_next_word(fio) < 0) {
1224 short i = td_getbuf;
1227 return (i < 0) ? 1 : 0;
1230 static int td_get_byte(FILEIO* fio)
1232 if(td_next_word(fio) != 0) {
1235 uint16 i = td_getbuf;
1242 static void td_start_huff()
1245 for(i = 0; i < N_CHAR; i++) {
1247 td_son[i] = i + TABLE_SIZE;
1248 td_prnt[i + TABLE_SIZE] = i;
1251 while(j <= ROOT_POSITION) {
1252 td_freq[j] = td_freq[i] + td_freq[i + 1];
1254 td_prnt[i] = td_prnt[i + 1] = j;
1257 td_freq[TABLE_SIZE] = 0xffff;
1258 td_prnt[ROOT_POSITION] = 0;
1261 static void td_reconst()
1265 for(i = 0; i < TABLE_SIZE; i++) {
1266 if(td_son[i] >= TABLE_SIZE) {
1267 td_freq[j] = (td_freq[i] + 1) / 2;
1268 td_son[j] = td_son[i];
1272 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1274 f = td_freq[j] = td_freq[i] + td_freq[k];
1275 for(k = j - 1; f < td_freq[k]; k--);
1278 memmove(&td_freq[k + 1], &td_freq[k], l);
1280 memmove(&td_son[k + 1], &td_son[k], l);
1283 for(i = 0; i < TABLE_SIZE; i++) {
1284 if((k = td_son[i]) >= TABLE_SIZE) {
1287 td_prnt[k] = td_prnt[k + 1] = i;
1292 static void td_update(int c)
1295 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1298 c = td_prnt[c + TABLE_SIZE];
1301 if(k > td_freq[l = c + 1]) {
1302 while(k > td_freq[++l]);
1304 td_freq[c] = td_freq[l];
1308 if(i < TABLE_SIZE) {
1314 if(j < TABLE_SIZE) {
1321 while((c = td_prnt[c]) != 0);
1324 static short td_decode_char(FILEIO* fio)
1327 uint16 c = td_son[ROOT_POSITION];
1328 while(c < TABLE_SIZE) {
1329 if((ret = td_get_bit(fio)) < 0) {
1340 static short td_decode_position(FILEIO* fio)
1344 if((bit = td_get_byte(fio)) < 0) {
1348 c = (uint16)td_d_code[i] << 6;
1349 j = td_d_len[i] - 2;
1351 if((bit = td_get_bit(fio)) < 0) {
1356 return (c | i & 0x3f);
1359 static void td_init_decode()
1361 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1364 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1365 td_text_buf[i] = ' ';
1367 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1370 static int td_decode(FILEIO* fio, uint8 *buf, int len)
1374 for(count = 0; count < len;) {
1375 if(td_bufcnt == 0) {
1376 if((c = td_decode_char(fio)) < 0) {
1380 *(buf++) = (uint8)c;
1381 td_text_buf[td_ptr++] = (uint8)c;
1382 td_ptr &= (STRING_BUFFER_SIZE - 1);
1385 if((pos = td_decode_position(fio)) < 0) {
1388 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1389 td_bufcnt = c - 255 + THRESHOLD;
1393 while(td_bufndx < td_bufcnt && count < len) {
1394 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1395 *(buf++) = (uint8)c;
1397 td_text_buf[td_ptr++] = (uint8)c;
1398 td_ptr &= (STRING_BUFFER_SIZE - 1);
1401 if(td_bufndx >= td_bufcnt) {
1402 td_bufndx = td_bufcnt = 0;
1429 uint8 nsec, trk, head;
1438 bool DISK::teledisk_to_d88(FILEIO *fio)
1445 bool temporary = false;
1447 // check teledisk header
1448 fio->Fseek(0, FILEIO_SEEK_SET);
1449 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1450 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1451 // this image is compressed
1452 // decompress to the temporary file
1453 FILEIO* fio_tmp = new FILEIO();
1454 if(!fio_tmp->Fopen(local_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1461 if((rd = td_decode(fio, obuf, 512)) > 0) {
1462 fio_tmp->Fwrite(obuf, rd, 1);
1470 // reopen the temporary file
1472 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1475 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1476 // this image is not compressed
1480 if(hdr.flag & 0x80) {
1482 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1483 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1486 // create d88 header
1490 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1491 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1492 d88_hdr.protect = 0; // non-protected
1495 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1498 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1499 fio->Fread(&trk, sizeof(td_trk_t), 1);
1500 while(trk.nsec != 0xff) {
1501 d88_hdr.trkptr[trkcnt++] = trkptr;
1502 if(hdr.sides == 1) {
1506 // read sectors in this track
1507 for(int i = 0; i < trk.nsec; i++) {
1508 uint8 buf[2048], dst[2048];
1509 memset(buf, 0, sizeof(buf));
1510 memset(dst, 0, sizeof(dst));
1512 // read sector header
1513 fio->Fread(&sct, sizeof(td_sct_t), 1);
1515 // create d88 sector header
1516 memset(&d88_sct, 0, sizeof(d88_sct_t));
1521 d88_sct.nsec = trk.nsec;
1522 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1523 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1524 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1525 d88_sct.size = secsize[sct.n & 3];
1527 // create sector image
1528 if(sct.ctrl & 0x30) {
1529 d88_sct.stat = 0xf0; // data mark missing
1532 // read sector source
1533 int len = fio->Fgetc();
1534 len += fio->Fgetc() * 256 - 1;
1535 int flag = fio->Fgetc(), d = 0;
1536 fio->Fread(buf, len, 1);
1540 memcpy(dst, buf, len);
1541 } else if(flag == 1) {
1543 len2.read_2bytes_le_from(buf);
1548 } else if(flag == 2) {
1549 for(int s = 0; s < len;) {
1550 int type = buf[s++];
1551 int len2 = buf[s++];
1554 dst[d++] = buf[s++];
1556 } else if(type < 5) {
1562 for(int j = 0; j < n; j++) {
1566 for(int j = 0; j < n; j++) {
1571 break; // unknown type
1575 break; // unknown flag
1580 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1581 COPYBUFFER(dst, d88_sct.size);
1582 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1585 fio->Fread(&trk, sizeof(td_trk_t), 1);
1587 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1588 d88_hdr.size = trkptr;
1589 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1592 FILEIO::RemoveFile(_T("teledisk.$$$"));
1597 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
1599 bool DISK::imagedisk_to_d88(FILEIO *fio)
1601 int size = fio->FileLength();
1602 fio->Fseek(0, FILEIO_SEEK_SET);
1603 fio->Fread(tmp_buffer, size, 1);
1605 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
1610 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
1617 // create d88 header
1621 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1622 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
1623 d88_hdr.protect = 0; // non-protected
1626 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1629 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1634 // check track header
1635 uint8 mode = tmp_buffer[pos++];
1636 uint8 track = tmp_buffer[pos++];
1637 uint8 head = tmp_buffer[pos++];
1638 uint8 sector_count = tmp_buffer[pos++];
1639 uint8 ssize = tmp_buffer[pos++];
1641 if(sector_count == 0) {
1647 uint32 actual_size = ssize < 7 ? 128 << ssize : 8192;
1650 const uint8 *snum = &tmp_buffer[pos];
1651 pos += sector_count;
1652 const uint8 *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
1654 pos += sector_count;
1655 const uint8 *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
1657 pos += sector_count;
1661 int trkside = track * 2 + (head & 1);
1663 if(trkcnt < trkside) {
1666 d88_hdr.trkptr[trkside] = trkptr;
1668 if(img_mode == -1) {
1669 img_mode = mode & 3;
1672 // read sectors in this track
1673 for(int i = 0; i < sector_count; i++) {
1674 // create d88 sector header
1675 uint8 stype = tmp_buffer[pos++];
1676 memset(&d88_sct, 0, sizeof(d88_sct_t));
1677 d88_sct.c = tnum ? tnum[i] : track;
1678 d88_sct.h = hnum ? hnum[i] : head;
1679 d88_sct.r = snum[i];
1681 d88_sct.nsec = sector_count;
1682 d88_sct.dens = (mode < 3) ? 0x40 : 0;
1684 if(stype == 0 || stype > 8) {
1685 d88_sct.stat = 0xf0; // data mark missing
1688 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
1689 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
1690 d88_sct.size = actual_size;
1692 // create sector image
1693 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
1694 memset(dst, tmp_buffer[pos++], actual_size);
1696 memcpy(dst, &tmp_buffer[pos], actual_size);
1697 pos += d88_sct.size;
1703 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1704 COPYBUFFER(dst, d88_sct.size);
1705 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1709 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1710 d88_hdr.size = trkptr;
1711 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1715 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
1717 #define DSK_FORMAT_HEADER "MV - CPC"
1718 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
1721 struct track_header {
1722 uint8 headertag[13];
1729 uint8 sector_size_code;
1730 uint8 number_of_sector;
1734 struct sector_header {
1738 uint8 sector_size_code;
1739 uint8 fdc_status_reg1;
1740 uint8 fdc_status_reg2;
1745 bool DISK::cpdread_to_d88(FILEIO *fio)
1747 bool extendformat = false;
1748 int image_size = fio->FileLength();
1750 fio->Fseek(0, FILEIO_SEEK_SET);
1751 fio->Fread(tmp_buffer, image_size, 1);
1753 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
1754 extendformat = true;
1755 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
1756 extendformat = false;
1761 int heads = tmp_buffer[0x31];
1766 int tracks = tmp_buffer[0x30];
1767 int track_offsets[84 * 2];
1768 bool track_offsets_error = false;
1770 int cnt = 0, tmp = 0x100;
1771 for(int i = 0; i < tracks * heads; i++) {
1772 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1775 track_offsets[cnt] = tmp;
1776 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
1780 int cnt = 0, tmp = 0x100;
1781 for(int i = 0; i < tracks * heads; i++) {
1782 int length = tmp_buffer[0x34 + i] << 8;
1784 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1787 track_offsets[cnt] = tmp;
1790 track_offsets[cnt] = image_size;
1795 if(track_offsets_error) {
1796 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
1797 // so I modified this code to search "Track-Info" at the top of track information block
1798 int cnt = 0, tmp = 0x100;
1799 for(int i = 0; i < tracks * heads; i++) {
1801 for(; tmp < image_size; tmp += 0x10) {
1802 if(found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0)) {
1807 track_offsets[cnt] = tmp;
1810 track_offsets[cnt] = image_size;
1816 // create d88 header
1820 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1821 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
1822 d88_hdr.protect = 0; // non-protected
1825 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1828 int total = 0, trkptr = sizeof(d88_hdr_t);
1830 for(int track = 0; track < tracks; track++) {
1831 for(int side = 0; side < heads; side++) {
1832 if(track_offsets[(track << 1) + side] >= image_size) {
1835 if((track << 1) + side < 164) {
1836 d88_hdr.trkptr[(track << 1) + side] = trkptr;
1840 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
1841 int pos = track_offsets[(track << 1) + side] + 0x100;
1842 for(int j = 0; j < tr.number_of_sector; j++) {
1843 sector_header sector;
1844 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
1846 // create d88 sector header
1847 memset(&d88_sct, 0, sizeof(d88_sct_t));
1848 d88_sct.c = sector.track;
1849 d88_sct.h = sector.side;
1850 d88_sct.r = sector.sector_id;
1851 d88_sct.n = sector.sector_size_code;
1852 d88_sct.nsec = tr.number_of_sector;
1854 d88_sct.size = sector.data_length;
1855 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
1857 d88_sct.size = 128 << tr.sector_size_code;
1858 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
1860 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
1861 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
1864 if((track << 1) + side < 164) {
1865 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1866 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
1867 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1869 total += d88_sct.size;
1872 pos += sector.data_length;
1874 pos += 128 << tr.sector_size_code;
1879 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
1880 d88_hdr.size = trkptr;
1881 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1885 // solid image decoder
1887 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
1893 solid_nside = nside;
1898 // create d88 header
1902 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1903 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
1904 d88_hdr.protect = 0; // non-protected
1907 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1910 for(int i = 0; i < 8; i++) {
1911 if(size == (128 << i)) {
1918 int trkptr = sizeof(d88_hdr_t);
1920 for(int c = 0; c < ncyl; c++) {
1921 for(int h = 0; h < nside; h++) {
1922 d88_hdr.trkptr[t++] = trkptr;
1927 // read sectors in this track
1928 for(int s = 0; s < nsec; s++) {
1929 // create d88 sector header
1930 memset(&d88_sct, 0, sizeof(d88_sct_t));
1935 d88_sct.nsec = nsec;
1939 d88_sct.size = size;
1941 // create sector image
1943 memset(dst, 0xe5, sizeof(dst));
1944 fio->Fread(dst, size, 1);
1947 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1948 COPYBUFFER(dst, size);
1949 trkptr += sizeof(d88_sct_t) + size;
1953 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
1954 d88_hdr.size = trkptr;
1955 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1959 #define STATE_VERSION 11
1961 void DISK::save_state(FILEIO* state_fio)
1963 state_fio->FputUint32(STATE_VERSION);
1965 state_fio->Fwrite(buffer, sizeof(buffer), 1);
1966 state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
1967 state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
1968 state_fio->FputUint32(file_size.d);
1969 state_fio->FputInt32(file_bank);
1970 state_fio->FputUint32(crc32);
1971 state_fio->FputBool(trim_required);
1972 state_fio->FputBool(is_1dd_image);
1973 state_fio->FputBool(is_solid_image);
1974 state_fio->FputBool(is_fdi_image);
1975 state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
1976 state_fio->FputInt32(solid_ncyl);
1977 state_fio->FputInt32(solid_nside);
1978 state_fio->FputInt32(solid_nsec);
1979 state_fio->FputInt32(solid_size);
1980 state_fio->FputBool(solid_mfm);
1981 state_fio->FputBool(inserted);
1982 state_fio->FputBool(ejected);
1983 state_fio->FputBool(write_protected);
1984 state_fio->FputBool(changed);
1985 state_fio->FputUint8(media_type);
1986 state_fio->FputInt32(is_special_disk);
1987 state_fio->Fwrite(track, sizeof(track), 1);
1988 state_fio->FputInt32(sector_num.sd);
1989 state_fio->FputBool(track_mfm);
1990 state_fio->FputBool(invalid_format);
1991 // state_fio->FputBool(no_skew);
1992 state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
1993 state_fio->Fwrite(am1_position, sizeof(am1_position), 1);
1994 state_fio->Fwrite(id_position, sizeof(id_position), 1);
1995 state_fio->Fwrite(data_position, sizeof(data_position), 1);
1996 state_fio->FputInt32(gap3_size);
1997 state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
1998 state_fio->FputInt32(sector_size.sd);
1999 state_fio->Fwrite(id, sizeof(id), 1);
2000 state_fio->FputUint8(density);
2001 state_fio->FputBool(deleted);
2002 state_fio->FputBool(addr_crc_error);
2003 state_fio->FputBool(data_crc_error);
2004 state_fio->FputUint8(drive_type);
2005 state_fio->FputInt32(drive_rpm);
2006 state_fio->FputBool(drive_mfm);
2009 bool DISK::load_state(FILEIO* state_fio)
2011 if(state_fio->FgetUint32() != STATE_VERSION) {
2014 state_fio->Fread(buffer, sizeof(buffer), 1);
2015 state_fio->Fread(orig_path, sizeof(orig_path), 1);
2016 state_fio->Fread(dest_path, sizeof(dest_path), 1);
2017 file_size.d = state_fio->FgetUint32();
2018 file_bank = state_fio->FgetInt32();
2019 crc32 = state_fio->FgetUint32();
2020 trim_required = state_fio->FgetBool();
2021 is_1dd_image = state_fio->FgetBool();
2022 is_solid_image = state_fio->FgetBool();
2023 is_fdi_image = state_fio->FgetBool();
2024 state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
2025 solid_ncyl = state_fio->FgetInt32();
2026 solid_nside = state_fio->FgetInt32();
2027 solid_nsec = state_fio->FgetInt32();
2028 solid_size = state_fio->FgetInt32();
2029 solid_mfm = state_fio->FgetBool();
2030 inserted = state_fio->FgetBool();
2031 ejected = state_fio->FgetBool();
2032 write_protected = state_fio->FgetBool();
2033 changed = state_fio->FgetBool();
2034 media_type = state_fio->FgetUint8();
2035 is_special_disk = state_fio->FgetInt32();
2036 state_fio->Fread(track, sizeof(track), 1);
2037 sector_num.sd = state_fio->FgetInt32();
2038 track_mfm = state_fio->FgetBool();
2039 invalid_format = state_fio->FgetBool();
2040 // no_skew = state_fio->FgetBool();
2041 state_fio->Fread(sync_position, sizeof(sync_position), 1);
2042 state_fio->Fread(am1_position, sizeof(am1_position), 1);
2043 state_fio->Fread(id_position, sizeof(id_position), 1);
2044 state_fio->Fread(data_position, sizeof(data_position), 1);
2045 gap3_size = state_fio->FgetInt32();
2046 int offset = state_fio->FgetInt32();
2047 sector = (offset != -1) ? buffer + offset : NULL;
2048 sector_size.sd = state_fio->FgetInt32();
2049 state_fio->Fread(id, sizeof(id), 1);
2050 density = state_fio->FgetUint8();
2051 deleted = state_fio->FgetBool();
2052 addr_crc_error = state_fio->FgetBool();
2053 data_crc_error = state_fio->FgetBool();
2054 drive_type = state_fio->FgetUint8();
2055 drive_rpm = state_fio->FgetInt32();
2056 drive_mfm = state_fio->FgetBool();