2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 #include "../config.h"
12 #include "../fileio.h"
15 #define bios_path(x) emu->bios_path(x)
17 #define bios_path(x) (x)
21 # define min(a,b) (a > b) ? b : a
25 static const uint16 crc_table[256] = {
26 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
27 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
28 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
29 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
30 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
31 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
32 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
33 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
34 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
35 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
36 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
37 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
38 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
39 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
40 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
41 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
44 static const int secsize[8] = {
45 128, 256, 512, 1024, 2048, 4096, 8192, 16384
48 static uint8 tmp_buffer[DISK_BUFFER_SIZE];
50 // physical format table for solid image
53 int ncyl, nside, nsec, size;
60 static const fd_format_t fd_formats[] = {
62 { MEDIA_TYPE_2D, 40, 1, 16, 256, MFM }, // 1D 160KB
63 #elif defined(_SMC70) || defined(_SMC777)
64 { MEDIA_TYPE_2DD, 70, 1, 16, 256, MFM }, // 1DD 280KB
65 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
66 { MEDIA_TYPE_2D, 40, 2, 16, 256, MFM }, // 2D 320KB
68 { MEDIA_TYPE_2D, 40, 2, 18, 256, MFM }, // 2D 360KB
69 #elif defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200) || defined(_MZ2500)
70 { MEDIA_TYPE_2DD, 80, 2, 16, 256, MFM }, // 2DD 640KB
72 { MEDIA_TYPE_2D, 35, 1, 16, 128, FM }, // 1S 70KB
73 { MEDIA_TYPE_2D, 35, 2, 16, 128, FM }, // 2S 140KB
74 { MEDIA_TYPE_2DD, 77, 1, 26, 128, FM }, // 1S 250KB
75 { MEDIA_TYPE_2D, 40, 1, 8, 512, MFM }, // 1D 160KB
76 { MEDIA_TYPE_2D, 40, 1, 9, 512, MFM }, // 1D 180KB
77 { MEDIA_TYPE_2D, 40, 1, 10, 512, MFM }, // 1D 200KB
78 //#if defined(SUPPORT_MEDIA_TYPE_1DD)
79 // { MEDIA_TYPE_2DD, 70, 1, 8, 512, MFM }, // 1DD 280KB
80 // { MEDIA_TYPE_2DD, 70, 1, 9, 512, MFM }, // 1DD 315KB
81 // { MEDIA_TYPE_2DD, 70, 1, 10, 512, MFM }, // 1DD 350KB
82 // { MEDIA_TYPE_2DD, 80, 1, 8, 512, MFM }, // 1DD 320KB
83 // { MEDIA_TYPE_2DD, 80, 1, 9, 512, MFM }, // 1DD 360KB
84 // { MEDIA_TYPE_2DD, 80, 1, 10, 512, MFM }, // 1DD 400KB
86 { MEDIA_TYPE_2D, 35, 2, 8, 512, MFM }, // 2D 280KB
87 { MEDIA_TYPE_2D, 35, 2, 9, 512, MFM }, // 2D 315KB
88 { MEDIA_TYPE_2D, 35, 2, 10, 512, MFM }, // 2D 350KB
89 { MEDIA_TYPE_2D, 40, 2, 8, 512, MFM }, // 2D 320KB
90 { MEDIA_TYPE_2D, 40, 2, 9, 512, MFM }, // 2D 360KB
91 { MEDIA_TYPE_2D, 40, 2, 10, 512, MFM }, // 2D 400KB
93 { MEDIA_TYPE_2DD, 80, 2, 8, 512, MFM }, // 2DD 640KB
94 { MEDIA_TYPE_2DD, 80, 2, 9, 512, MFM }, // 2DD 720KB
95 { MEDIA_TYPE_2DD, 81, 2, 9, 512, MFM }, // 2DD 729KB, ASCII MSX
96 { MEDIA_TYPE_2DD, 80, 2, 10, 512, MFM }, // 2DD 800KB
97 { MEDIA_TYPE_2HD, 77, 2, 26, 256, MFM }, // 2HD 1001KB, MITSUBISHI/IBM
98 { MEDIA_TYPE_2HD, 80, 2, 15, 512, MFM }, // 2HC 1200KB, TOSHIBA/IBM
99 { MEDIA_TYPE_2HD, 77, 2, 8, 1024, MFM }, // 2HD 1232KB, NEC
100 { MEDIA_TYPE_144, 80, 2, 18, 512, MFM }, // 2HD 1440KB
101 { MEDIA_TYPE_144, 80, 2, 21, 512, MFM }, // 2HD 1680KB
102 { MEDIA_TYPE_144, 82, 2, 21, 512, MFM }, // 2HD 1722KB
103 { MEDIA_TYPE_144, 80, 2, 36, 512, MFM }, // 2ED 2880KB
107 #define IS_VALID_TRACK(offset) ((offset) >= 0x20 && (offset) < sizeof(buffer))
109 void DISK::open(const _TCHAR* file_path, int bank)
111 // check current disk image
113 if(_tcsicmp(orig_path, file_path) == 0 && file_bank == bank) {
118 memset(buffer, 0, sizeof(buffer));
120 write_protected = false;
121 media_type = MEDIA_TYPE_UNK;
122 is_solid_image = is_fdi_image = is_1dd_image = false;
123 trim_required = false;
124 track_mfm = drive_mfm;
127 FILEIO *fio = new FILEIO();
128 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
129 _tcscpy_s(orig_path, _MAX_PATH, file_path);
130 _tcscpy_s(dest_path, _MAX_PATH, file_path);
132 file_size.d = fio->FileLength();
133 fio->Fseek(0, FILEIO_SEEK_SET);
135 if(check_file_extension(file_path, _T(".d88")) || check_file_extension(file_path, _T(".d77")) || check_file_extension(file_path, _T(".1dd"))) {
138 for(int i = 0; i < bank; i++) {
139 fio->Fseek(offset + 0x1c, SEEK_SET);
140 offset += fio->FgetUint32_LE();
142 fio->Fseek(offset + 0x1c, FILEIO_SEEK_SET);
143 file_size.d = fio->FgetUint32_LE();
144 fio->Fseek(offset, FILEIO_SEEK_SET);
145 fio->Fread(buffer, file_size.d, 1);
147 if(check_file_extension(file_path, _T(".1dd"))) {
149 media_type = MEDIA_TYPE_2DD;
151 inserted = changed = true;
152 // trim_required = true;
154 // fix sector number from big endian to little endian
155 for(int trkside = 0; trkside < 164; trkside++) {
157 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
159 if(!IS_VALID_TRACK(offset.d)) {
162 uint8* t = buffer + offset.d;
163 pair sector_num, data_size;
164 sector_num.read_2bytes_le_from(t + 4);
165 bool is_be = (sector_num.b.l == 0 && sector_num.b.h >= 4);
167 sector_num.read_2bytes_be_from(t + 4);
168 sector_num.write_2bytes_le_to(t + 4);
170 for(int i = 0; i < sector_num.sd; i++) {
172 sector_num.write_2bytes_le_to(t + 4);
174 data_size.read_2bytes_le_from(t + 14);
175 t += data_size.sd + 0x10;
178 } else if(check_file_extension(file_path, _T(".td0"))) {
181 inserted = changed = teledisk_to_d88(fio);
182 _stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
184 // failed to convert the disk image
186 } else if(check_file_extension(file_path, _T(".imd"))) {
189 inserted = changed = imagedisk_to_d88(fio);
190 _stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
192 // failed to convert the disk image
194 } else if(check_file_extension(file_path, _T(".dsk"))) {
197 inserted = changed = cpdread_to_d88(fio);
198 _stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), file_path);
200 // failed to convert the disk image
202 } else if(check_file_extension(file_path, _T(".2d")) && file_size.d == 40 * 2 * 16 * 256) {
203 // 2d image for SHARP X1 series
204 inserted = changed = is_solid_image = solid_to_d88(fio, MEDIA_TYPE_2D, 40, 2, 16, 256, true);
205 } else if(check_file_extension(file_path, _T(".img")) && file_size.d == 70 * 1 * 16 * 256) {
206 // img image for SONY SMC-70/777 series
207 inserted = changed = is_solid_image = solid_to_d88(fio, MEDIA_TYPE_2DD, 70, 1, 16, 256, true);
208 } else if(check_file_extension(file_path, _T(".sf7")) && file_size.d == 40 * 1 * 16 * 256) {
209 // sf7 image for SEGA SC-3000 + SF-7000
210 inserted = changed = is_solid_image = solid_to_d88(fio, MEDIA_TYPE_2D, 40, 1, 16, 256, true);
213 // check solid image file format
214 bool is_fdi_tmp = check_file_extension(file_path, _T(".fdi"));
215 for(int i = 0;; i++) {
216 const fd_format_t *p = &fd_formats[i];
220 int len = p->ncyl * p->nside * p->nsec * p->size;
221 // 4096 bytes: FDI header ???
222 if(file_size.d == len + (is_fdi_tmp ? 4096 : 0)) {
223 fio->Fseek(0, FILEIO_SEEK_SET);
226 fio->Fread(fdi_header, 4096, 1);
230 int nside = p->nside;
233 #if defined(SUPPORT_MEDIA_TYPE_1DD)
234 if(type == MEDIA_TYPE_2D && nside == 2 && p->mfm) {
235 type = MEDIA_TYPE_2DD;
239 #elif defined(_ANY2D88)
240 if(open_as_1dd && type == MEDIA_TYPE_2D && nside == 2 && p->mfm) {
241 type = MEDIA_TYPE_2DD;
245 if(open_as_256 && (size == 512 || size == 1024)) {
250 // if(solid_to_d88(fio, p->type, p->ncyl, p->nside, p->nsec, p->size, p->mfm)) {
251 if(solid_to_d88(fio, type, ncyl, nside, nsec, size, p->mfm)) {
252 inserted = changed = is_solid_image = true;
258 if(fio->IsOpened()) {
262 if(buffer[0x1a] != 0) {
264 write_protected = true;
266 crc32 = getcrc32(buffer, file_size.d);
268 if(media_type == MEDIA_TYPE_UNK) {
269 if((media_type = buffer[0x1b]) == MEDIA_TYPE_2HD) {
270 for(int trkside = 0; trkside < 164; trkside++) {
272 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
274 if(!IS_VALID_TRACK(offset.d)) {
278 uint8 *t = buffer + offset.d;
279 pair sector_num, data_size;
280 sector_num.read_2bytes_le_from(t + 4);
281 data_size.read_2bytes_le_from(t + 14);
283 if(sector_num.sd >= 18 && data_size.sd == 512) {
284 media_type = MEDIA_TYPE_144;
291 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
292 // FIXME: ugly patch for FM-7 Gambler Jiko Chuushin Ha and DEATH FORCE
293 if(media_type == MEDIA_TYPE_2D) {
295 pair offset, sector_num, data_size;
296 offset.read_4bytes_le_from(buffer + 0x20);
297 if(IS_VALID_TRACK(offset.d)) {
298 // check the sector (c,h,r,n) = (0,0,7,1) or (0,0,f7,2)
299 uint8* t = buffer + offset.d;
300 sector_num.read_2bytes_le_from(t + 4);
301 for(int i = 0; i < sector_num.sd; i++) {
302 data_size.read_2bytes_le_from(t + 14);
303 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 7 && t[3] == 1) {
304 static const uint8 gambler[] = {0xb7, 0xde, 0xad, 0xdc, 0xdd, 0xcc, 0xde, 0xd7, 0xb1, 0x20, 0xbc, 0xde, 0xba, 0xc1, 0xad, 0xb3, 0xbc, 0xdd, 0xca};
305 if(memcmp((void *)(t + 0x30), gambler, sizeof(gambler)) == 0) {
306 is_special_disk = SPECIAL_DISK_FM7_GAMBLER;
309 } else if(data_size.sd == 0x200 && t[0] == 0 && t[1] == 0 && t[2] == 0xf7 && t[3] == 2) {
310 //"DEATHFORCE/77AV" + $f7*17 + $00 + $00
311 static const uint8 deathforce[] ={
312 0x44, 0x45, 0x41, 0x54, 0x48, 0x46, 0x4f, 0x52,
313 0x43, 0x45, 0x2f, 0x37, 0x37, 0x41, 0x56, 0xf7,
314 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
315 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
318 if(memcmp((void *)(t + 0x10), deathforce, sizeof(deathforce)) == 0) {
319 is_special_disk = SPECIAL_DISK_FM7_DEATHFORCE;
323 t += data_size.sd + 0x10;
325 if(is_special_disk == 0) {
326 t = buffer + offset.d;
327 sector_num.read_2bytes_le_from(t + 4);
329 for(int i = 0; i < sector_num.sd; i++) {
330 data_size.read_2bytes_le_from(t + 14);
331 // FIXME : Check DEATH FORCE
332 if(data_size.sd == 0x200 && t[0] == 0 && t[1] == 0 && t[2] == 0xf7 && t[3] == 0x02) {
333 static const uint8 deathforce[] ={
334 0x44, 0x45, 0x41, 0x54, 0x48, 0x46, 0x4f, 0x52,
335 0x43, 0x45, 0x2f, 0x37, 0x37, 0x41, 0x56, 0xf7,
336 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
337 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
338 0x00, 0x00}; //"DEATHFORCE/77AV" + $f7*17 + $00 + $00
339 if(memcmp((void *)(t + 0x10), deathforce, sizeof(deathforce)) == 0) {
340 is_special_disk = SPECIAL_DISK_FM7_DEATHFORCE;
344 t += data_size.sd + 0x10;
347 if(is_special_disk == 0) {
348 t = buffer + offset.d;
349 sector_num.read_2bytes_le_from(t + 4);
351 for(int i = 0; i < sector_num.sd; i++) {
352 data_size.read_2bytes_le_from(t + 14);
353 // FIXME : Check Psy-O-Blade (Program)
354 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 0x01 && t[3] == 0x01) {
355 static const uint8 psyoblade_ipl1[] ={
356 0x03, 0x2d, 0x50, 0x53, 0x59, 0xa5, 0x4f, 0xa5,
357 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20, 0x20, 0x20,
358 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
359 0x74, 0x20, 0x31, 0x39, 0x38, 0x38, 0x20, 0x62,
360 0x79, 0x20, 0x54, 0x26, 0x45, 0x20, 0x53, 0x4f,
361 0x46, 0x54, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0xb6,
363 //$03 + $2D + "PSY-O-BLADE Copyright 1988 by T&E SOFT Inc" + $B6 + $FD + $05
364 if(memcmp((void *)(t + 0x58), psyoblade_ipl1, sizeof(psyoblade_ipl1)) == 0) {
365 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
366 //printf("Disk: PSY-O-BLADE\n");
370 t += data_size.sd + 0x10;
373 if(is_special_disk == 0) {
374 t = buffer + offset.d;
375 sector_num.read_2bytes_le_from(t + 4);
377 for(int i = 0; i < sector_num.sd; i++) {
378 data_size.read_2bytes_le_from(t + 14);
379 // FIXME : Check Psy-O-Blade (Program)
380 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 0x01 && t[3] == 0x01) {
382 static const uint8 psyoblade_disk_1[] ={
383 0xc3, 0x00, 0x01, 0x00, 0x1a, 0x50, 0x86, 0xff,
384 0xb7, 0xfd, 0x10, 0xb7, 0xfd, 0x0f, 0x30, 0x8c,
385 0x0e, 0x8d, 0x35, 0x30, 0x8c, 0x14, 0x8d, 0x30,
386 0x30, 0x8c, 0x14, 0x8d, 0x2b, 0x20, 0xfe, 0x0a,
388 //$00 + $00 + $03 + $14 + "PSY-O-BLADE DISK" + $B6 + $FD + $05
389 static const uint8 psyoblade_disk_2[] ={
390 0x00, 0x00, 0x03, 0x14, 0x50, 0x53, 0x59, 0xa5,
391 0x4f, 0xa5, 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20,
392 0x20, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20};
393 if(memcmp((void *)(t + 0x10), psyoblade_disk_1, sizeof(psyoblade_disk_1)) == 0) {
394 if(memcmp((void *)(t + 0x40), psyoblade_disk_2, sizeof(psyoblade_disk_2)) == 0) {
395 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
396 //printf("Disk: PSY-O-BLADE\n");
401 t += data_size.sd + 0x10;
406 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
407 // FIXME: ugly patch for X1turbo ALPHA and X1 Batten Tanuki
408 if(media_type == MEDIA_TYPE_2D) {
411 offset.read_4bytes_le_from(buffer + 0x20);
412 if(IS_VALID_TRACK(offset.d)) {
413 // check first sector
414 static const uint8 batten[] = {0xca, 0xde, 0xaf, 0xc3, 0xdd, 0x20, 0xc0, 0xc7, 0xb7};
415 uint8 *t = buffer + offset.d;
416 #if defined(_X1TURBO) || defined(_X1TURBOZ)
417 // if(strncmp((char *)(t + 0x11), "turbo ALPHA", 11) == 0) {
418 // is_special_disk = SPECIAL_DISK_X1TURBO_ALPHA;
421 if(memcmp((void *)(t + 0x11), batten, sizeof(batten)) == 0) {
422 is_special_disk = SPECIAL_DISK_X1_BATTEN;
437 trim_required = false;
439 buffer[0x1a] = write_protected ? 0x10 : 0; // mey be changed
441 if(/*!write_protected &&*/ file_size.d && getcrc32(buffer, file_size.d) != crc32) {
443 FILEIO* fio = new FILEIO();
444 int pre_size = 0, post_size = 0;
445 uint8 *pre_buffer = NULL, *post_buffer = NULL;
447 // is this d88 format ?
448 if(check_file_extension(dest_path, _T(".d88")) || check_file_extension(dest_path, _T(".d77")) || check_file_extension(dest_path, _T(".1dd"))) {
449 if(fio->Fopen(dest_path, FILEIO_READ_BINARY)) {
450 fio->Fseek(0, FILEIO_SEEK_END);
451 uint32 total_size = fio->Ftell(), offset = 0;
452 for(int i = 0; i < file_bank; i++) {
453 fio->Fseek(offset + 0x1c, SEEK_SET);
454 offset += fio->FgetUint32_LE();
456 if((pre_size = offset) > 0) {
457 pre_buffer = (uint8 *)malloc(pre_size);
458 fio->Fseek(0, FILEIO_SEEK_SET);
459 fio->Fread(pre_buffer, pre_size, 1);
461 fio->Fseek(offset + 0x1c, SEEK_SET);
462 offset += fio->FgetUint32_LE();
463 if((post_size = total_size - offset) > 0) {
464 post_buffer = (uint8 *)malloc(post_size);
465 fio->Fseek(offset, FILEIO_SEEK_SET);
466 fio->Fread(post_buffer, post_size, 1);
472 // is this solid image and was physical formatted ?
474 bool formatted = false;
477 for(int trkside = 0; trkside < 164; trkside++) {
479 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
481 if(!IS_VALID_TRACK(offset.d)) {
484 if(solid_nside == 1 && (trkside & 1) == 1) {
489 uint8* t = buffer + offset.d;
490 pair sector_num, data_size;
491 sector_num.read_2bytes_le_from(t + 4);
493 if(sector_num.sd != solid_nsec) {
496 for(int i = 0; i < sector_num.sd; i++) {
497 data_size.read_2bytes_le_from(t + 14);
498 if(data_size.sd != solid_size) {
501 if(t[6] != (solid_mfm ? 0 : 0x40)) {
504 t += data_size.sd + 0x10;
507 if(tracks != (solid_ncyl * solid_nside)) {
511 _stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), orig_path);
512 is_solid_image = false;
516 if((FILEIO::IsFileExists(dest_path) && FILEIO::IsFileProtected(dest_path)) || !fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
517 _TCHAR tmp_path[_MAX_PATH];
518 _stprintf_s(tmp_path, _MAX_PATH, _T("temporary_saved_floppy_disk_#%d.d88"), drive_num);
519 fio->Fopen(bios_path(tmp_path), FILEIO_WRITE_BINARY);
521 if(fio->IsOpened()) {
523 fio->Fwrite(pre_buffer, pre_size, 1);
527 fio->Fwrite(fdi_header, 4096, 1);
529 for(int trkside = 0; trkside < 164; trkside++) {
531 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
533 if(!IS_VALID_TRACK(offset.d)) {
536 uint8* t = buffer + offset.d;
537 pair sector_num, data_size;
538 sector_num.read_2bytes_le_from(t + 4);
540 for(int i = 0; i < sector_num.sd; i++) {
541 data_size.read_2bytes_le_from(t + 14);
542 fio->Fwrite(t + 0x10, data_size.sd, 1);
543 t += data_size.sd + 0x10;
547 fio->Fwrite(buffer, file_size.d, 1);
550 fio->Fwrite(post_buffer, post_size, 1);
564 inserted = write_protected = false;
566 sector_size.sd = sector_num.sd = 0;
571 void DISK::save_as_d88(const _TCHAR* file_path)
574 FILEIO* fio = new FILEIO();
575 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
577 memcpy(tmp_buffer, buffer + 0x20, 4 * 82);
578 for(int trk = 0; trk < 82; trk++) {
579 memcpy(buffer + 0x20 + (trk * 2 + 0) * 4, tmp_buffer + trk * 4, 4);
580 memset(buffer + 0x20 + (trk * 2 + 1) * 4, 0, 4);
582 buffer[0x1b] = MEDIA_TYPE_2DD;
584 fio->Fwrite(buffer, file_size.d, 1);
592 bool DISK::get_track(int trk, int side)
594 sector_size.sd = sector_num.sd = 0;
595 invalid_format = false;
598 // disk not inserted or invalid media type
599 if(!(inserted && check_media_type())) {
603 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
604 if(!(0 <= trkside && trkside < 164)) {
611 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
613 if(!IS_VALID_TRACK(offset.d)) {
618 sector = buffer + offset.d;
619 sector_num.read_2bytes_le_from(sector + 4);
621 data_size.read_2bytes_le_from(sector + 14);
623 // create each sector position in track
625 if(sector_num.sd == 0) {
626 track_mfm = drive_mfm;
629 for(int i = 0; i < sector_num.sd; i++) {
630 data_size.read_2bytes_le_from(t + 14);
631 // t[6]: 0x00 = double-density, 0x40 = single-density
636 t += data_size.sd + 0x10;
639 int sync_size = track_mfm ? 12 : 6;
640 int am_size = track_mfm ? 3 : 0;
641 int gap0_size = track_mfm ? 80 : 40;
642 int gap1_size = track_mfm ? 50 : 26;
643 int gap2_size = track_mfm ? 22 : 11;
644 int gap3_size = 0, gap4_size;
646 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
648 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
649 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
650 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
652 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
653 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
654 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
658 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
659 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
660 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
662 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
663 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
664 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
669 int total = sync_size + (am_size + 1);
671 for(int i = 0; i < sector_num.sd; i++) {
672 data_size.read_2bytes_le_from(t + 14);
673 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
674 if(data_size.sd > 0) {
675 total += sync_size + (am_size + 1);
676 total += data_size.sd + 2;
678 // if(t[2] != i + 1) {
681 t += data_size.sd + 0x10;
684 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (sector_num.sd + 1);
686 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
688 if(gap3_size < 8 || gap4_size < 8) {
689 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + sector_num.sd + 1);
690 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
692 if(gap3_size < 8 || gap4_size < 8) {
693 gap0_size = gap1_size = gap3_size = gap4_size = 32;
694 invalid_format = true;
696 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
699 total = preamble_size;
700 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
702 for(int i = 0; i < sector_num.sd; i++) {
703 data_size.read_2bytes_le_from(t + 14);
705 total = preamble_size + (get_track_size() - preamble_size - gap4_size) * i / sector_num.sd;
707 sync_position[i] = total;
709 am1_position[i] = total;
710 total += am_size + 1;
711 id_position[i] = total;
712 total += (4 + 2) + gap2_size;
713 if(data_size.sd > 0) {
714 total += sync_size + (am_size + 1);
715 data_position[i] = total;
716 total += data_size.sd + 2;
718 data_position[i] = total; // FIXME
721 t += data_size.sd + 0x10;
726 bool DISK::make_track(int trk, int side)
728 int track_size = get_track_size();
730 if(!get_track(trk, side)) {
731 // create a dummy track
732 for(int i = 0; i < track_size; i++) {
739 int sync_size = track_mfm ? 12 : 6;
740 int am_size = track_mfm ? 3 : 0;
741 int gap2_size = track_mfm ? 22 : 11;
742 uint8 gap_data = track_mfm ? 0x4e : 0xff;
745 memset(track, gap_data, track_size);
746 int q = sync_position[array_length(sync_position) - 1];
749 for(int i = 0; i < sync_size; i++) {
753 for(int i = 0; i < am_size; i++) {
761 for(int i = 0; i < sector_num.sd; i++) {
763 data_size.read_2bytes_le_from(t + 14);
764 int p = sync_position[i];
767 for(int j = 0; j < sync_size; j++) {
768 if(p < track_size) track[p++] = 0x00;
771 for(int j = 0; j < am_size; j++) {
772 if(p < track_size) track[p++] = 0xa1;
774 if(p < track_size) track[p++] = 0xfe;
776 if(p < track_size) track[p++] = t[0];
777 if(p < track_size) track[p++] = t[1];
778 if(p < track_size) track[p++] = t[2];
779 if(p < track_size) track[p++] = t[3];
781 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
782 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
783 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
784 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
785 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
786 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
788 for(int j = 0; j < gap2_size; j++) {
789 if(p < track_size) track[p++] = gap_data;
792 if(data_size.sd > 0) {
794 for(int j = 0; j < sync_size; j++) {
795 if(p < track_size) track[p++] = 0x00;
798 for(int j = 0; j < am_size; j++) {
799 if(p < track_size) track[p++] = 0xa1;
801 if(p < track_size) track[p++] = (t[7] != 0) ? 0xf8 : 0xfb;
804 for(int j = 0; j < data_size.sd; j++) {
805 if(p < track_size) track[p++] = t[0x10 + j];
806 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0x10 + j]]);
808 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
809 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
811 t += data_size.sd + 0x10;
816 bool DISK::get_sector(int trk, int side, int index)
818 sector_size.sd = sector_num.sd = 0;
821 // disk not inserted or invalid media type
822 if(!(inserted && check_media_type())) {
827 if(trk == -1 && side == -1) {
831 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
832 if(!(0 <= trkside && trkside < 164)) {
836 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
838 if(!IS_VALID_TRACK(offset.d)) {
843 uint8* t = buffer + offset.d;
844 sector_num.read_2bytes_le_from(t + 4);
846 if(index >= sector_num.sd) {
851 for(int i = 0; i < index; i++) {
853 data_size.read_2bytes_le_from(t + 14);
854 t += data_size.sd + 0x10;
860 void DISK::set_sector_info(uint8 *t)
868 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
869 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
870 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
871 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
872 id[4] = (crc >> 8) & 0xff;
873 id[5] = (crc >> 0) & 0xff;
874 // http://www,gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
875 // t[6]: 0x00 = double-density, 0x40 = single-density
876 // t[7]: 0x00 = normal, 0x10 = deleted mark
877 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
879 deleted = (t[7] != 0);
881 // if(ignore_crc()) {
882 // crc_error = false;
884 // crc_error = (((t[8] & 0xf0) != 0x00) && ((t[8] & 0xf0) != 0x10));
885 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
886 data_crc_error = ((t[8] & 0xf0) == 0xb0);
889 sector_size.read_2bytes_le_from(t + 14);
892 void DISK::set_deleted(bool value)
895 uint8 *t = sector - 0x10;
896 t[7] = value ? 0x10 : 0;
897 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
898 t[8] = (t[8] & 0x0f) | t[7];
904 void DISK::set_data_crc_error(bool value)
907 uint8 *t = sector - 0x10;
908 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
910 data_crc_error = value;
913 void DISK::set_data_mark_missing()
916 uint8 *t = sector - 0x10;
917 //t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]); // FIXME: always data crc error ?
918 t[8] = (t[8] & 0x0f) | 0xf0;
922 //addr_crc_error = value;
923 data_crc_error = false;
926 bool DISK::format_track(int trk, int side)
928 // disk not inserted or invalid media type
929 if(!(inserted && check_media_type())) {
934 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
935 if(!(0 <= trkside && trkside < 164)) {
939 // create new empty track
942 trim_required = false;
944 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
946 offset.d = DISK_BUFFER_SIZE;
947 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
949 trim_required = true;
951 track_mfm = drive_mfm;
956 void DISK::insert_sector(uint8 c, uint8 h, uint8 r, uint8 n, bool deleted, bool data_crc_error, uint8 fill_data, int length)
958 uint8* t = buffer + DISK_BUFFER_SIZE;
961 for(int i = 0; i < (sector_num.sd - 1); i++) {
962 t[4] = sector_num.b.l;
963 t[5] = sector_num.b.h;
965 data_size.read_2bytes_le_from(t + 14);
966 t += data_size.sd + 0x10;
972 t[4] = sector_num.b.l;
973 t[5] = sector_num.b.h;
974 t[6] = track_mfm ? 0 : 0x40;
975 t[7] = deleted ? 0x10 : 0;
976 t[8] = data_crc_error ? 0xb0 : t[7];
977 t[14] = (length >> 0) & 0xff;
978 t[15] = (length >> 8) & 0xff;
979 memset(t + 16, fill_data, length);
984 void DISK::sync_buffer()
988 trim_required = false;
992 void DISK::trim_buffer()
994 int max_tracks = 164;
995 uint32 dest_offset = 0x2b0;
998 memset(tmp_buffer, 0, sizeof(tmp_buffer));
999 memcpy(tmp_buffer, buffer, 0x20);
1002 for(int trkside = 0; trkside < 164; trkside++) {
1003 pair src_trk_offset;
1004 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1005 if(src_trk_offset.d != 0) {
1007 if(src_trk_offset.d < 0x2b0) {
1008 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1011 if(src_trk_offset.d != 0x2b0) {
1012 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1013 if(max_tracks > 164) {
1014 dest_offset = 0x20 + max_tracks * 4);
1023 for(int trkside = 0; trkside < max_tracks; trkside++) {
1024 pair src_trk_offset;
1025 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1027 pair dest_trk_offset;
1028 dest_trk_offset.d = 0;
1030 if(IS_VALID_TRACK(src_trk_offset.d)) {
1031 uint8* t = buffer + src_trk_offset.d;
1032 pair sector_num, data_size;
1033 sector_num.read_2bytes_le_from(t + 4);
1034 if(sector_num.sd != 0) {
1035 dest_trk_offset.d = dest_offset;
1036 for(int i = 0; i < sector_num.sd; i++) {
1037 data_size.read_2bytes_le_from(t + 14);
1038 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
1039 dest_offset += data_size.sd + 0x10;
1040 t += data_size.sd + 0x10;
1044 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
1048 file_size.d = dest_offset;
1049 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
1051 memset(buffer, 0, sizeof(buffer));
1052 memcpy(buffer, tmp_buffer, min(sizeof(buffer), file_size.d));
1053 //memcpy(buffer, tmp_buffer, (file_size.d > sizeof(buffer)) ? sizeof(buffer) : file_size.d);
1058 if(drive_rpm != 0) {
1060 } else if(inserted) {
1061 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
1063 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
1067 int DISK::get_track_size()
1070 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1071 if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
1072 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3100;
1075 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : track_mfm ? 6250 : 3100;
1077 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1078 if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
1079 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3100;
1082 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
1086 double DISK::get_usec_per_track()
1088 return 1000000.0 / (get_rpm() / 60.0);
1091 double DISK::get_usec_per_bytes(int bytes)
1093 #if defined(_FM77AV_VARIANTS)
1094 if(is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE) {
1095 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0) * 2.0) * bytes;
1098 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1101 int DISK::get_bytes_per_usec(double usec)
1103 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1106 bool DISK::check_media_type()
1108 switch(drive_type) {
1110 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1111 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
1112 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1114 return (media_type == MEDIA_TYPE_2D);
1116 case DRIVE_TYPE_2DD:
1117 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1118 case DRIVE_TYPE_2HD:
1119 return (media_type == MEDIA_TYPE_2HD);
1120 case DRIVE_TYPE_144:
1121 return (media_type == MEDIA_TYPE_144);
1122 case DRIVE_TYPE_UNK:
1123 return true; // always okay
1130 #define COPYBUFFER(src, size) { \
1131 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1134 memcpy(buffer + file_size.d, (src), (size)); \
1135 file_size.d += (size); \
1150 uint8 dens, del, stat;
1155 // teledisk image decoder
1158 this teledisk image decoder is based on:
1160 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1161 LZSS coded by Haruhiko OKUMURA
1162 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1163 Edited and translated to English by Kenji RIKITAKE
1167 #define STRING_BUFFER_SIZE 4096
1168 #define LOOKAHEAD_BUFFER_SIZE 60
1170 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1171 #define TABLE_SIZE (N_CHAR * 2 - 1)
1172 #define ROOT_POSITION (TABLE_SIZE - 1)
1173 #define MAX_FREQ 0x8000
1175 static uint8 td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1176 static uint16 td_ptr;
1177 static uint16 td_bufcnt, td_bufndx, td_bufpos;
1178 static uint16 td_ibufcnt, td_ibufndx;
1179 static uint8 td_inbuf[512];
1180 static uint16 td_freq[TABLE_SIZE + 1];
1181 static short td_prnt[TABLE_SIZE + N_CHAR];
1182 static short td_son[TABLE_SIZE];
1183 static uint16 td_getbuf;
1184 static uint8 td_getlen;
1186 static const uint8 td_d_code[256] = {
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1189 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1190 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1191 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1192 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1193 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1194 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1195 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1196 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1197 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1198 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1199 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1200 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1201 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1202 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1204 static const uint8 td_d_len[256] = {
1205 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1206 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1207 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1208 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1209 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1210 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1211 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1212 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1213 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1214 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1215 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1216 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1217 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1218 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1219 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1220 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1223 static int td_next_word(FILEIO* fio)
1225 if(td_ibufndx >= td_ibufcnt) {
1226 td_ibufndx = td_ibufcnt = 0;
1227 memset(td_inbuf, 0, 512);
1228 for(int i = 0; i < 512; i++) {
1229 int d = fio->Fgetc();
1240 while(td_getlen <= 8) {
1241 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1247 static int td_get_bit(FILEIO* fio)
1249 if(td_next_word(fio) < 0) {
1252 short i = td_getbuf;
1255 return (i < 0) ? 1 : 0;
1258 static int td_get_byte(FILEIO* fio)
1260 if(td_next_word(fio) != 0) {
1263 uint16 i = td_getbuf;
1270 static void td_start_huff()
1273 for(i = 0; i < N_CHAR; i++) {
1275 td_son[i] = i + TABLE_SIZE;
1276 td_prnt[i + TABLE_SIZE] = i;
1279 while(j <= ROOT_POSITION) {
1280 td_freq[j] = td_freq[i] + td_freq[i + 1];
1282 td_prnt[i] = td_prnt[i + 1] = j;
1285 td_freq[TABLE_SIZE] = 0xffff;
1286 td_prnt[ROOT_POSITION] = 0;
1289 static void td_reconst()
1293 for(i = 0; i < TABLE_SIZE; i++) {
1294 if(td_son[i] >= TABLE_SIZE) {
1295 td_freq[j] = (td_freq[i] + 1) / 2;
1296 td_son[j] = td_son[i];
1300 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1302 f = td_freq[j] = td_freq[i] + td_freq[k];
1303 for(k = j - 1; f < td_freq[k]; k--);
1306 memmove(&td_freq[k + 1], &td_freq[k], l);
1308 memmove(&td_son[k + 1], &td_son[k], l);
1311 for(i = 0; i < TABLE_SIZE; i++) {
1312 if((k = td_son[i]) >= TABLE_SIZE) {
1315 td_prnt[k] = td_prnt[k + 1] = i;
1320 static void td_update(int c)
1323 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1326 c = td_prnt[c + TABLE_SIZE];
1329 if(k > td_freq[l = c + 1]) {
1330 while(k > td_freq[++l]);
1332 td_freq[c] = td_freq[l];
1336 if(i < TABLE_SIZE) {
1342 if(j < TABLE_SIZE) {
1349 while((c = td_prnt[c]) != 0);
1352 static short td_decode_char(FILEIO* fio)
1355 uint16 c = td_son[ROOT_POSITION];
1356 while(c < TABLE_SIZE) {
1357 if((ret = td_get_bit(fio)) < 0) {
1368 static short td_decode_position(FILEIO* fio)
1372 if((bit = td_get_byte(fio)) < 0) {
1376 c = (uint16)td_d_code[i] << 6;
1377 j = td_d_len[i] - 2;
1379 if((bit = td_get_bit(fio)) < 0) {
1384 return (c | i & 0x3f);
1387 static void td_init_decode()
1389 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1392 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1393 td_text_buf[i] = ' ';
1395 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1398 static int td_decode(FILEIO* fio, uint8 *buf, int len)
1402 for(count = 0; count < len;) {
1403 if(td_bufcnt == 0) {
1404 if((c = td_decode_char(fio)) < 0) {
1408 *(buf++) = (uint8)c;
1409 td_text_buf[td_ptr++] = (uint8)c;
1410 td_ptr &= (STRING_BUFFER_SIZE - 1);
1413 if((pos = td_decode_position(fio)) < 0) {
1416 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1417 td_bufcnt = c - 255 + THRESHOLD;
1421 while(td_bufndx < td_bufcnt && count < len) {
1422 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1423 *(buf++) = (uint8)c;
1425 td_text_buf[td_ptr++] = (uint8)c;
1426 td_ptr &= (STRING_BUFFER_SIZE - 1);
1429 if(td_bufndx >= td_bufcnt) {
1430 td_bufndx = td_bufcnt = 0;
1457 uint8 nsec, trk, head;
1466 bool DISK::teledisk_to_d88(FILEIO *fio)
1473 bool temporary = false;
1475 // check teledisk header
1476 fio->Fseek(0, FILEIO_SEEK_SET);
1477 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1478 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1479 // this image is compressed
1480 // decompress to the temporary file
1481 FILEIO* fio_tmp = new FILEIO();
1482 if(!fio_tmp->Fopen(bios_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1489 if((rd = td_decode(fio, obuf, 512)) > 0) {
1490 fio_tmp->Fwrite(obuf, rd, 1);
1498 // reopen the temporary file
1500 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1503 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1504 // this image is not compressed
1508 if(hdr.flag & 0x80) {
1510 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1511 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1514 // create d88 header
1518 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1519 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1520 d88_hdr.protect = 0; // non-protected
1523 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1526 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1527 fio->Fread(&trk, sizeof(td_trk_t), 1);
1528 while(trk.nsec != 0xff) {
1529 d88_hdr.trkptr[trkcnt++] = trkptr;
1530 if(hdr.sides == 1) {
1534 // read sectors in this track
1535 for(int i = 0; i < trk.nsec; i++) {
1536 uint8 buf[2048], dst[2048];
1537 memset(buf, 0, sizeof(buf));
1538 memset(dst, 0, sizeof(dst));
1540 // read sector header
1541 fio->Fread(&sct, sizeof(td_sct_t), 1);
1543 // create d88 sector header
1544 memset(&d88_sct, 0, sizeof(d88_sct_t));
1549 d88_sct.nsec = trk.nsec;
1550 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1551 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1552 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1553 d88_sct.size = secsize[sct.n & 3];
1555 // create sector image
1556 if(sct.ctrl & 0x30) {
1557 d88_sct.stat = 0xf0; // data mark missing
1560 // read sector source
1561 int len = fio->Fgetc();
1562 len += fio->Fgetc() * 256 - 1;
1563 int flag = fio->Fgetc(), d = 0;
1564 fio->Fread(buf, len, 1);
1568 memcpy(dst, buf, len);
1569 } else if(flag == 1) {
1571 len2.read_2bytes_le_from(buf);
1576 } else if(flag == 2) {
1577 for(int s = 0; s < len;) {
1578 int type = buf[s++];
1579 int len2 = buf[s++];
1582 dst[d++] = buf[s++];
1584 } else if(type < 5) {
1590 for(int j = 0; j < n; j++) {
1594 for(int j = 0; j < n; j++) {
1599 break; // unknown type
1603 break; // unknown flag
1608 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1609 COPYBUFFER(dst, d88_sct.size);
1610 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1613 fio->Fread(&trk, sizeof(td_trk_t), 1);
1615 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 45) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1616 d88_hdr.size = trkptr;
1617 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1620 FILEIO::RemoveFile(_T("teledisk.$$$"));
1625 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
1627 bool DISK::imagedisk_to_d88(FILEIO *fio)
1629 //d88_hdr_t d88_hdr;
1630 //d88_sct_t d88_sct;
1631 int size = fio->FileLength();
1632 fio->Fseek(0, FILEIO_SEEK_SET);
1633 fio->Fread(tmp_buffer, size, 1);
1635 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
1640 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
1647 // create d88 header
1651 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1652 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
1653 d88_hdr.protect = 0; // non-protected
1656 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1659 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1664 //for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
1668 // check track header
1669 uint8 mode = tmp_buffer[pos++];
1670 uint8 track = tmp_buffer[pos++];
1671 uint8 head = tmp_buffer[pos++];
1672 uint8 sector_count = tmp_buffer[pos++];
1673 uint8 ssize = tmp_buffer[pos++];
1675 if(sector_count == 0) {
1681 uint32 actual_size = ssize < 7 ? 128 << ssize : 8192;
1684 const uint8 *snum = &tmp_buffer[pos];
1685 pos += sector_count;
1686 const uint8 *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
1688 pos += sector_count;
1689 const uint8 *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
1691 pos += sector_count;
1695 int trkside = track * 2 + (head & 1);
1697 if(trkcnt < trkside) {
1700 d88_hdr.trkptr[trkside] = trkptr;
1702 if(img_mode == -1) {
1703 img_mode = mode & 3;
1706 // read sectors in this track
1707 for(int i = 0; i < sector_count; i++) {
1708 // create d88 sector header
1709 uint8 stype = tmp_buffer[pos++];
1710 memset(&d88_sct, 0, sizeof(d88_sct_t));
1711 d88_sct.c = tnum ? tnum[i] : track;
1712 d88_sct.h = hnum ? hnum[i] : head;
1713 d88_sct.r = snum[i];
1715 d88_sct.nsec = sector_count;
1716 d88_sct.dens = (mode < 3) ? 0x40 : 0;
1718 if(stype == 0 || stype > 8) {
1719 d88_sct.stat = 0xf0; // data mark missing
1722 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
1723 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
1724 d88_sct.size = actual_size;
1726 // create sector image
1727 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
1728 memset(dst, tmp_buffer[pos++], actual_size);
1730 memcpy(dst, &tmp_buffer[pos], actual_size);
1731 pos += d88_sct.size;
1737 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1738 COPYBUFFER(dst, d88_sct.size);
1739 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1743 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1744 d88_hdr.size = trkptr;
1745 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1749 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
1751 #define DSK_FORMAT_HEADER "MV - CPC"
1752 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
1755 struct track_header {
1756 uint8 headertag[13];
1763 uint8 sector_size_code;
1764 uint8 number_of_sector;
1768 struct sector_header {
1772 uint8 sector_size_code;
1773 uint8 fdc_status_reg1;
1774 uint8 fdc_status_reg2;
1779 bool DISK::cpdread_to_d88(FILEIO *fio)
1781 bool extendformat = false;
1782 int image_size = fio->FileLength();
1784 fio->Fseek(0, FILEIO_SEEK_SET);
1785 fio->Fread(tmp_buffer, image_size, 1);
1787 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
1788 extendformat = true;
1789 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
1790 extendformat = false;
1795 int heads = tmp_buffer[0x31];
1800 int tracks = tmp_buffer[0x30];
1801 int track_offsets[84 * 2];
1802 bool track_offsets_error = false;
1804 int cnt = 0, tmp = 0x100;
1805 for(int i = 0; i < tracks * heads; i++) {
1806 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1809 track_offsets[cnt] = tmp;
1810 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
1814 int cnt = 0, tmp = 0x100;
1815 for(int i = 0; i < tracks * heads; i++) {
1816 int length = tmp_buffer[0x34 + i] << 8;
1818 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1821 track_offsets[cnt] = tmp;
1824 track_offsets[cnt] = image_size;
1829 if(track_offsets_error) {
1830 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
1831 // so I modified this code to search "Track-Info" at the top of track information block
1832 int cnt = 0, tmp = 0x100;
1833 for(int i = 0; i < tracks * heads; i++) {
1835 for(; tmp < image_size; tmp += 0x10) {
1836 if(found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0)) {
1841 track_offsets[cnt] = tmp;
1844 track_offsets[cnt] = image_size;
1850 // create d88 header
1854 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1855 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
1856 d88_hdr.protect = 0; // non-protected
1859 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1862 int total = 0, trkptr = sizeof(d88_hdr_t);
1864 for(int track = 0; track < tracks; track++) {
1865 for(int side = 0; side < heads; side++) {
1866 if(track_offsets[(track << 1) + side] >= image_size) {
1869 if((track << 1) + side < 164) {
1870 d88_hdr.trkptr[(track << 1) + side] = trkptr;
1874 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
1875 int pos = track_offsets[(track << 1) + side] + 0x100;
1876 for(int j = 0; j < tr.number_of_sector; j++) {
1877 sector_header sector;
1878 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
1880 // create d88 sector header
1881 memset(&d88_sct, 0, sizeof(d88_sct_t));
1882 d88_sct.c = sector.track;
1883 d88_sct.h = sector.side;
1884 d88_sct.r = sector.sector_id;
1885 d88_sct.n = sector.sector_size_code;
1886 d88_sct.nsec = tr.number_of_sector;
1888 d88_sct.size = sector.data_length;
1889 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
1891 d88_sct.size = 128 << tr.sector_size_code;
1892 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
1894 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
1895 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
1898 if((track << 1) + side < 164) {
1899 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1900 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
1901 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1903 total += d88_sct.size;
1906 pos += sector.data_length;
1908 pos += 128 << tr.sector_size_code;
1913 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
1914 d88_hdr.size = trkptr;
1915 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1919 // solid image decoder
1921 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
1927 solid_nside = nside;
1932 // create d88 header
1936 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1937 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
1938 d88_hdr.protect = 0; // non-protected
1941 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1944 for(int i = 0; i < 8; i++) {
1945 if(size == (128 << i)) {
1952 int trkptr = sizeof(d88_hdr_t);
1954 for(int c = 0; c < ncyl; c++) {
1955 for(int h = 0; h < nside; h++) {
1956 d88_hdr.trkptr[t++] = trkptr;
1961 // read sectors in this track
1962 for(int s = 0; s < nsec; s++) {
1963 // create d88 sector header
1964 memset(&d88_sct, 0, sizeof(d88_sct_t));
1969 d88_sct.nsec = nsec;
1973 d88_sct.size = size;
1975 // create sector image
1977 memset(dst, 0xe5, sizeof(dst));
1978 fio->Fread(dst, size, 1);
1981 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1982 COPYBUFFER(dst, size);
1983 trkptr += sizeof(d88_sct_t) + size;
1987 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
1988 d88_hdr.size = trkptr;
1989 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1993 #define STATE_VERSION 10
1995 void DISK::save_state(FILEIO* state_fio)
1997 state_fio->FputUint32(STATE_VERSION);
1999 state_fio->Fwrite(buffer, sizeof(buffer), 1);
2000 state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
2001 state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
2002 state_fio->FputUint32(file_size.d);
2003 state_fio->FputInt32(file_bank);
2004 state_fio->FputUint32(crc32);
2005 state_fio->FputBool(trim_required);
2006 state_fio->FputBool(is_1dd_image);
2007 state_fio->FputBool(is_solid_image);
2008 state_fio->FputBool(is_fdi_image);
2009 state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
2010 state_fio->FputInt32(solid_ncyl);
2011 state_fio->FputInt32(solid_nside);
2012 state_fio->FputInt32(solid_nsec);
2013 state_fio->FputInt32(solid_size);
2014 state_fio->FputBool(solid_mfm);
2015 state_fio->FputBool(inserted);
2016 state_fio->FputBool(ejected);
2017 state_fio->FputBool(write_protected);
2018 state_fio->FputBool(changed);
2019 state_fio->FputUint8(media_type);
2020 state_fio->FputInt32(is_special_disk);
2021 state_fio->Fwrite(track, sizeof(track), 1);
2022 state_fio->FputInt32(sector_num.sd);
2023 state_fio->FputBool(track_mfm);
2024 state_fio->FputBool(invalid_format);
2025 // state_fio->FputBool(no_skew);
2026 state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
2027 state_fio->Fwrite(am1_position, sizeof(am1_position), 1);
2028 state_fio->Fwrite(id_position, sizeof(id_position), 1);
2029 state_fio->Fwrite(data_position, sizeof(data_position), 1);
2030 state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
2031 state_fio->FputInt32(sector_size.sd);
2032 state_fio->Fwrite(id, sizeof(id), 1);
2033 state_fio->FputUint8(density);
2034 state_fio->FputBool(deleted);
2035 state_fio->FputBool(addr_crc_error);
2036 state_fio->FputBool(data_crc_error);
2037 state_fio->FputUint8(drive_type);
2038 state_fio->FputInt32(drive_rpm);
2039 state_fio->FputBool(drive_mfm);
2042 bool DISK::load_state(FILEIO* state_fio)
2044 if(state_fio->FgetUint32() != STATE_VERSION) {
2047 state_fio->Fread(buffer, sizeof(buffer), 1);
2048 state_fio->Fread(orig_path, sizeof(orig_path), 1);
2049 state_fio->Fread(dest_path, sizeof(dest_path), 1);
2050 file_size.d = state_fio->FgetUint32();
2051 file_bank = state_fio->FgetInt32();
2052 crc32 = state_fio->FgetUint32();
2053 trim_required = state_fio->FgetBool();
2054 is_1dd_image = state_fio->FgetBool();
2055 is_solid_image = state_fio->FgetBool();
2056 is_fdi_image = state_fio->FgetBool();
2057 state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
2058 solid_ncyl = state_fio->FgetInt32();
2059 solid_nside = state_fio->FgetInt32();
2060 solid_nsec = state_fio->FgetInt32();
2061 solid_size = state_fio->FgetInt32();
2062 solid_mfm = state_fio->FgetBool();
2063 inserted = state_fio->FgetBool();
2064 ejected = state_fio->FgetBool();
2065 write_protected = state_fio->FgetBool();
2066 changed = state_fio->FgetBool();
2067 media_type = state_fio->FgetUint8();
2068 is_special_disk = state_fio->FgetInt32();
2069 state_fio->Fread(track, sizeof(track), 1);
2070 sector_num.sd = state_fio->FgetInt32();
2071 track_mfm = state_fio->FgetBool();
2072 invalid_format = state_fio->FgetBool();
2073 // no_skew = state_fio->FgetBool();
2074 state_fio->Fread(sync_position, sizeof(sync_position), 1);
2075 state_fio->Fread(am1_position, sizeof(am1_position), 1);
2076 state_fio->Fread(id_position, sizeof(id_position), 1);
2077 state_fio->Fread(data_position, sizeof(data_position), 1);
2078 int offset = state_fio->FgetInt32();
2079 sector = (offset != -1) ? buffer + offset : NULL;
2080 sector_size.sd = state_fio->FgetInt32();
2081 state_fio->Fread(id, sizeof(id), 1);
2082 density = state_fio->FgetUint8();
2083 deleted = state_fio->FgetBool();
2084 addr_crc_error = state_fio->FgetBool();
2085 data_crc_error = state_fio->FgetBool();
2086 drive_type = state_fio->FgetUint8();
2087 drive_rpm = state_fio->FgetInt32();
2088 drive_mfm = state_fio->FgetBool();