2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 #include "../config.h"
12 #include "../fileio.h"
15 #define local_path(x) create_local_path(x)
17 #define local_path(x) (x)
22 static const uint16 crc_table[256] = {
23 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
24 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
25 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
26 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
27 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
28 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
29 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
30 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
31 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
32 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
33 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
34 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
35 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
36 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
37 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
38 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
41 static const int secsize[8] = {
42 128, 256, 512, 1024, 2048, 4096, 8192, 16384
45 static uint8 tmp_buffer[DISK_BUFFER_SIZE];
47 // physical format table for solid image
50 int ncyl, nside, nsec, size;
57 static const fd_format_t fd_formats[] = {
59 { MEDIA_TYPE_2D, 40, 1, 16, 256, MFM }, // 1D 160KB
60 #elif defined(_SMC70) || defined(_SMC777)
61 { MEDIA_TYPE_2DD, 70, 1, 16, 256, MFM }, // 1DD 280KB
62 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
63 { MEDIA_TYPE_2D, 40, 2, 16, 256, MFM }, // 2D 320KB
65 { MEDIA_TYPE_2D, 40, 2, 18, 256, MFM }, // 2D 360KB
66 #elif defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200) || defined(_MZ2500)
67 { MEDIA_TYPE_2DD, 80, 2, 16, 256, MFM }, // 2DD 640KB
69 { MEDIA_TYPE_2D, 35, 1, 16, 128, FM }, // 1S 70KB
70 { MEDIA_TYPE_2D, 35, 2, 16, 128, FM }, // 2S 140KB
71 { MEDIA_TYPE_2DD, 77, 1, 26, 128, FM }, // 1S 250KB
72 { MEDIA_TYPE_2D, 40, 1, 8, 512, MFM }, // 1D 160KB
73 { MEDIA_TYPE_2D, 40, 1, 9, 512, MFM }, // 1D 180KB
74 { MEDIA_TYPE_2D, 40, 1, 10, 512, MFM }, // 1D 200KB
75 //#if defined(SUPPORT_MEDIA_TYPE_1DD)
76 // { MEDIA_TYPE_2DD, 70, 1, 8, 512, MFM }, // 1DD 280KB
77 // { MEDIA_TYPE_2DD, 70, 1, 9, 512, MFM }, // 1DD 315KB
78 // { MEDIA_TYPE_2DD, 70, 1, 10, 512, MFM }, // 1DD 350KB
79 // { MEDIA_TYPE_2DD, 80, 1, 8, 512, MFM }, // 1DD 320KB
80 // { MEDIA_TYPE_2DD, 80, 1, 9, 512, MFM }, // 1DD 360KB
81 // { MEDIA_TYPE_2DD, 80, 1, 10, 512, MFM }, // 1DD 400KB
83 { MEDIA_TYPE_2D, 35, 2, 8, 512, MFM }, // 2D 280KB
84 { MEDIA_TYPE_2D, 35, 2, 9, 512, MFM }, // 2D 315KB
85 { MEDIA_TYPE_2D, 35, 2, 10, 512, MFM }, // 2D 350KB
86 { MEDIA_TYPE_2D, 40, 2, 8, 512, MFM }, // 2D 320KB
87 { MEDIA_TYPE_2D, 40, 2, 9, 512, MFM }, // 2D 360KB
88 { MEDIA_TYPE_2D, 40, 2, 10, 512, MFM }, // 2D 400KB
90 { MEDIA_TYPE_2DD, 80, 2, 8, 512, MFM }, // 2DD 640KB
91 { MEDIA_TYPE_2DD, 80, 2, 9, 512, MFM }, // 2DD 720KB
92 { MEDIA_TYPE_2DD, 81, 2, 9, 512, MFM }, // 2DD 729KB, ASCII MSX
93 { MEDIA_TYPE_2DD, 80, 2, 10, 512, MFM }, // 2DD 800KB
94 { MEDIA_TYPE_2HD, 77, 2, 26, 256, MFM }, // 2HD 1001KB, MITSUBISHI/IBM
95 { MEDIA_TYPE_2HD, 80, 2, 15, 512, MFM }, // 2HC 1200KB, TOSHIBA/IBM
96 { MEDIA_TYPE_2HD, 77, 2, 8, 1024, MFM }, // 2HD 1232KB, NEC
97 { MEDIA_TYPE_144, 80, 2, 18, 512, MFM }, // 2HD 1440KB
98 { MEDIA_TYPE_144, 80, 2, 21, 512, MFM }, // 2HD 1680KB
99 { MEDIA_TYPE_144, 82, 2, 21, 512, MFM }, // 2HD 1722KB
100 { MEDIA_TYPE_144, 80, 2, 36, 512, MFM }, // 2ED 2880KB
104 #define IS_VALID_TRACK(offset) ((offset) >= 0x20 && (offset) < sizeof(buffer))
106 void DISK::open(const _TCHAR* file_path, int bank)
108 // check current disk image
110 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 my_tcscpy_s(orig_path, _MAX_PATH, file_path);
130 my_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 my_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 my_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 my_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, DEATH FORCE and Psy-O-Blade
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;
322 } else if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 1 && t[3] == 1) {
323 //$03 + $2D + "PSY-O-BLADE Copyright 1988 by T&E SOFT Inc" + $B6 + $FD + $05
324 static const uint8 psyoblade_ipl1[] ={
325 0x03, 0x2d, 0x50, 0x53, 0x59, 0xa5, 0x4f, 0xa5,
326 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20, 0x20, 0x20,
327 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
328 0x74, 0x20, 0x31, 0x39, 0x38, 0x38, 0x20, 0x62,
329 0x79, 0x20, 0x54, 0x26, 0x45, 0x20, 0x53, 0x4f,
330 0x46, 0x54, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0xb6,
334 static const uint8 psyoblade_disk_1[] ={
335 0xc3, 0x00, 0x01, 0x00, 0x1a, 0x50, 0x86, 0xff,
336 0xb7, 0xfd, 0x10, 0xb7, 0xfd, 0x0f, 0x30, 0x8c,
337 0x0e, 0x8d, 0x35, 0x30, 0x8c, 0x14, 0x8d, 0x30,
338 0x30, 0x8c, 0x14, 0x8d, 0x2b, 0x20, 0xfe, 0x0a,
340 //$00 + $00 + $03 + $14 + "PSY-O-BLADE DISK" + $B6 + $FD + $05
341 static const uint8 psyoblade_disk_2[] ={
342 0x00, 0x00, 0x03, 0x14, 0x50, 0x53, 0x59, 0xa5,
343 0x4f, 0xa5, 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20,
344 0x20, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20
346 if(memcmp((void *)(t + 0x58), psyoblade_ipl1, sizeof(psyoblade_ipl1)) == 0) {
347 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
349 } else if(memcmp((void *)(t + 0x10), psyoblade_disk_1, sizeof(psyoblade_disk_1)) == 0) {
350 if(memcmp((void *)(t + 0x40), psyoblade_disk_2, sizeof(psyoblade_disk_2)) == 0) {
351 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
356 t += data_size.sd + 0x10;
358 if(is_special_disk == 0) {
359 t = buffer + offset.d;
360 sector_num.read_2bytes_le_from(t + 4);
362 for(int i = 0; i < sector_num.sd; i++) {
363 data_size.read_2bytes_le_from(t + 14);
364 // FIXME : Check DEATH FORCE
365 if(data_size.sd == 0x200 && t[0] == 0 && t[1] == 0 && t[2] == 0xf7 && t[3] == 0x02) {
366 static const uint8 deathforce[] ={
367 0x44, 0x45, 0x41, 0x54, 0x48, 0x46, 0x4f, 0x52,
368 0x43, 0x45, 0x2f, 0x37, 0x37, 0x41, 0x56, 0xf7,
369 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
370 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
371 0x00, 0x00}; //"DEATHFORCE/77AV" + $f7*17 + $00 + $00
372 if(memcmp((void *)(t + 0x10), deathforce, sizeof(deathforce)) == 0) {
373 is_special_disk = SPECIAL_DISK_FM7_DEATHFORCE;
377 t += data_size.sd + 0x10;
380 if(is_special_disk == 0) {
381 t = buffer + offset.d;
382 sector_num.read_2bytes_le_from(t + 4);
384 for(int i = 0; i < sector_num.sd; i++) {
385 data_size.read_2bytes_le_from(t + 14);
386 // FIXME : Check Psy-O-Blade (Program)
387 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 0x01 && t[3] == 0x01) {
388 static const uint8 psyoblade_ipl1[] ={
389 0x03, 0x2d, 0x50, 0x53, 0x59, 0xa5, 0x4f, 0xa5,
390 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20, 0x20, 0x20,
391 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
392 0x74, 0x20, 0x31, 0x39, 0x38, 0x38, 0x20, 0x62,
393 0x79, 0x20, 0x54, 0x26, 0x45, 0x20, 0x53, 0x4f,
394 0x46, 0x54, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0xb6,
396 //$03 + $2D + "PSY-O-BLADE Copyright 1988 by T&E SOFT Inc" + $B6 + $FD + $05
397 if(memcmp((void *)(t + 0x58), psyoblade_ipl1, sizeof(psyoblade_ipl1)) == 0) {
398 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
399 //printf("Disk: PSY-O-BLADE\n");
403 t += data_size.sd + 0x10;
406 if(is_special_disk == 0) {
407 t = buffer + offset.d;
408 sector_num.read_2bytes_le_from(t + 4);
410 for(int i = 0; i < sector_num.sd; i++) {
411 data_size.read_2bytes_le_from(t + 14);
412 // FIXME : Check Psy-O-Blade (Program)
413 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 0x01 && t[3] == 0x01) {
415 static const uint8 psyoblade_disk_1[] ={
416 0xc3, 0x00, 0x01, 0x00, 0x1a, 0x50, 0x86, 0xff,
417 0xb7, 0xfd, 0x10, 0xb7, 0xfd, 0x0f, 0x30, 0x8c,
418 0x0e, 0x8d, 0x35, 0x30, 0x8c, 0x14, 0x8d, 0x30,
419 0x30, 0x8c, 0x14, 0x8d, 0x2b, 0x20, 0xfe, 0x0a,
421 //$00 + $00 + $03 + $14 + "PSY-O-BLADE DISK" + $B6 + $FD + $05
422 static const uint8 psyoblade_disk_2[] ={
423 0x00, 0x00, 0x03, 0x14, 0x50, 0x53, 0x59, 0xa5,
424 0x4f, 0xa5, 0x42, 0x4c, 0x41, 0x44, 0x45, 0x20,
425 0x20, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20};
426 if(memcmp((void *)(t + 0x10), psyoblade_disk_1, sizeof(psyoblade_disk_1)) == 0) {
427 if(memcmp((void *)(t + 0x40), psyoblade_disk_2, sizeof(psyoblade_disk_2)) == 0) {
428 is_special_disk = SPECIAL_DISK_FM77AV_PSYOBLADE;
429 //printf("Disk: PSY-O-BLADE\n");
434 t += data_size.sd + 0x10;
439 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
440 // FIXME: ugly patch for X1turbo ALPHA and X1 Batten Tanuki
441 if(media_type == MEDIA_TYPE_2D) {
444 offset.read_4bytes_le_from(buffer + 0x20);
445 if(IS_VALID_TRACK(offset.d)) {
446 // check first sector
447 static const uint8 batten[] = {0xca, 0xde, 0xaf, 0xc3, 0xdd, 0x20, 0xc0, 0xc7, 0xb7};
448 uint8 *t = buffer + offset.d;
449 #if defined(_X1TURBO) || defined(_X1TURBOZ)
450 // if(strncmp((char *)(t + 0x11), "turbo ALPHA", 11) == 0) {
451 // is_special_disk = SPECIAL_DISK_X1TURBO_ALPHA;
454 if(memcmp((void *)(t + 0x11), batten, sizeof(batten)) == 0) {
455 is_special_disk = SPECIAL_DISK_X1_BATTEN;
470 trim_required = false;
472 buffer[0x1a] = write_protected ? 0x10 : 0; // mey be changed
474 if(/*!write_protected &&*/ file_size.d && getcrc32(buffer, file_size.d) != crc32) {
476 FILEIO* fio = new FILEIO();
477 int pre_size = 0, post_size = 0;
478 uint8 *pre_buffer = NULL, *post_buffer = NULL;
480 // is this d88 format ?
481 if(check_file_extension(dest_path, _T(".d88")) || check_file_extension(dest_path, _T(".d77")) || check_file_extension(dest_path, _T(".1dd"))) {
482 if(fio->Fopen(dest_path, FILEIO_READ_BINARY)) {
483 fio->Fseek(0, FILEIO_SEEK_END);
484 uint32 total_size = fio->Ftell(), offset = 0;
485 for(int i = 0; i < file_bank; i++) {
486 fio->Fseek(offset + 0x1c, SEEK_SET);
487 offset += fio->FgetUint32_LE();
489 if((pre_size = offset) > 0) {
490 pre_buffer = (uint8 *)malloc(pre_size);
491 fio->Fseek(0, FILEIO_SEEK_SET);
492 fio->Fread(pre_buffer, pre_size, 1);
494 fio->Fseek(offset + 0x1c, SEEK_SET);
495 offset += fio->FgetUint32_LE();
496 if((post_size = total_size - offset) > 0) {
497 post_buffer = (uint8 *)malloc(post_size);
498 fio->Fseek(offset, FILEIO_SEEK_SET);
499 fio->Fread(post_buffer, post_size, 1);
505 // is this solid image and was physical formatted ?
507 bool formatted = false;
510 for(int trkside = 0; trkside < 164; trkside++) {
512 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
514 if(!IS_VALID_TRACK(offset.d)) {
517 if(solid_nside == 1 && (trkside & 1) == 1) {
522 uint8* t = buffer + offset.d;
523 pair sector_num, data_size;
524 sector_num.read_2bytes_le_from(t + 4);
526 if(sector_num.sd != solid_nsec) {
529 for(int i = 0; i < sector_num.sd; i++) {
530 data_size.read_2bytes_le_from(t + 14);
531 if(data_size.sd != solid_size) {
534 if(t[6] != (solid_mfm ? 0 : 0x40)) {
537 t += data_size.sd + 0x10;
540 if(tracks != (solid_ncyl * solid_nside)) {
544 my_stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), orig_path);
545 is_solid_image = false;
549 if((FILEIO::IsFileExists(dest_path) && FILEIO::IsFileProtected(dest_path)) || !fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
550 _TCHAR tmp_path[_MAX_PATH];
551 my_stprintf_s(tmp_path, _MAX_PATH, _T("temporary_saved_floppy_disk_#%d.d88"), drive_num);
552 fio->Fopen(local_path(tmp_path), FILEIO_WRITE_BINARY);
554 if(fio->IsOpened()) {
556 fio->Fwrite(pre_buffer, pre_size, 1);
560 fio->Fwrite(fdi_header, 4096, 1);
562 for(int trkside = 0; trkside < 164; trkside++) {
564 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
566 if(!IS_VALID_TRACK(offset.d)) {
569 uint8* t = buffer + offset.d;
570 pair sector_num, data_size;
571 sector_num.read_2bytes_le_from(t + 4);
573 for(int i = 0; i < sector_num.sd; i++) {
574 data_size.read_2bytes_le_from(t + 14);
575 fio->Fwrite(t + 0x10, data_size.sd, 1);
576 t += data_size.sd + 0x10;
580 fio->Fwrite(buffer, file_size.d, 1);
583 fio->Fwrite(post_buffer, post_size, 1);
597 inserted = write_protected = false;
599 sector_size.sd = sector_num.sd = 0;
604 void DISK::save_as_d88(const _TCHAR* file_path)
607 FILEIO* fio = new FILEIO();
608 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
610 memcpy(tmp_buffer, buffer + 0x20, 4 * 82);
611 for(int trk = 0; trk < 82; trk++) {
612 memcpy(buffer + 0x20 + (trk * 2 + 0) * 4, tmp_buffer + trk * 4, 4);
613 memset(buffer + 0x20 + (trk * 2 + 1) * 4, 0, 4);
615 buffer[0x1b] = MEDIA_TYPE_2DD;
617 fio->Fwrite(buffer, file_size.d, 1);
625 bool DISK::get_track(int trk, int side)
627 sector_size.sd = sector_num.sd = 0;
628 invalid_format = false;
631 // disk not inserted or invalid media type
632 if(!(inserted && check_media_type())) {
636 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
637 if(!(0 <= trkside && trkside < 164)) {
644 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
646 if(!IS_VALID_TRACK(offset.d)) {
651 sector = buffer + offset.d;
652 sector_num.read_2bytes_le_from(sector + 4);
654 data_size.read_2bytes_le_from(sector + 14);
656 // create each sector position in track
658 if(sector_num.sd == 0) {
659 track_mfm = drive_mfm;
662 for(int i = 0; i < sector_num.sd; i++) {
663 data_size.read_2bytes_le_from(t + 14);
664 // t[6]: 0x00 = double-density, 0x40 = single-density
669 t += data_size.sd + 0x10;
672 int sync_size = track_mfm ? 12 : 6;
673 int am_size = track_mfm ? 3 : 0;
674 int gap0_size = track_mfm ? 80 : 40;
675 int gap1_size = track_mfm ? 50 : 26;
676 int gap2_size = track_mfm ? 22 : 11;
677 int gap3_size = 0, gap4_size;
679 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
681 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
682 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
683 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
685 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
686 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
687 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
691 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
692 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
693 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
695 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
696 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
697 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
702 int total = sync_size + (am_size + 1);
704 for(int i = 0; i < sector_num.sd; i++) {
705 data_size.read_2bytes_le_from(t + 14);
706 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
707 if(data_size.sd > 0) {
708 total += sync_size + (am_size + 1);
709 total += data_size.sd + 2;
711 // if(t[2] != i + 1) {
714 t += data_size.sd + 0x10;
717 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (sector_num.sd + 1);
719 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
721 if(gap3_size < 8 || gap4_size < 8) {
722 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + sector_num.sd + 1);
723 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
725 if(gap3_size < 8 || gap4_size < 8) {
726 gap0_size = gap1_size = gap3_size = gap4_size = 32;
727 invalid_format = true;
729 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
732 total = preamble_size;
733 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
735 for(int i = 0; i < sector_num.sd; i++) {
736 data_size.read_2bytes_le_from(t + 14);
738 total = preamble_size + (get_track_size() - preamble_size - gap4_size) * i / sector_num.sd;
740 sync_position[i] = total;
742 am1_position[i] = total;
743 total += am_size + 1;
744 id_position[i] = total;
745 total += (4 + 2) + gap2_size;
746 if(data_size.sd > 0) {
747 total += sync_size + (am_size + 1);
748 data_position[i] = total;
749 total += data_size.sd + 2;
751 data_position[i] = total; // FIXME
754 t += data_size.sd + 0x10;
759 bool DISK::make_track(int trk, int side)
761 int track_size = get_track_size();
763 if(!get_track(trk, side)) {
764 // create a dummy track
765 for(int i = 0; i < track_size; i++) {
772 int sync_size = track_mfm ? 12 : 6;
773 int am_size = track_mfm ? 3 : 0;
774 int gap2_size = track_mfm ? 22 : 11;
775 uint8 gap_data = track_mfm ? 0x4e : 0xff;
778 memset(track, gap_data, track_size);
779 int q = sync_position[array_length(sync_position) - 1];
782 for(int i = 0; i < sync_size; i++) {
786 for(int i = 0; i < am_size; i++) {
794 for(int i = 0; i < sector_num.sd; i++) {
796 data_size.read_2bytes_le_from(t + 14);
797 int p = sync_position[i];
800 for(int j = 0; j < sync_size; j++) {
801 if(p < track_size) track[p++] = 0x00;
804 for(int j = 0; j < am_size; j++) {
805 if(p < track_size) track[p++] = 0xa1;
807 if(p < track_size) track[p++] = 0xfe;
809 if(p < track_size) track[p++] = t[0];
810 if(p < track_size) track[p++] = t[1];
811 if(p < track_size) track[p++] = t[2];
812 if(p < track_size) track[p++] = t[3];
814 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
815 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
816 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
817 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
818 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
819 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
821 for(int j = 0; j < gap2_size; j++) {
822 if(p < track_size) track[p++] = gap_data;
825 if(data_size.sd > 0) {
827 for(int j = 0; j < sync_size; j++) {
828 if(p < track_size) track[p++] = 0x00;
831 for(int j = 0; j < am_size; j++) {
832 if(p < track_size) track[p++] = 0xa1;
834 if(p < track_size) track[p++] = (t[7] != 0) ? 0xf8 : 0xfb;
837 for(int j = 0; j < data_size.sd; j++) {
838 if(p < track_size) track[p++] = t[0x10 + j];
839 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0x10 + j]]);
841 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
842 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
844 t += data_size.sd + 0x10;
849 bool DISK::get_sector(int trk, int side, int index)
851 sector_size.sd = sector_num.sd = 0;
854 // disk not inserted or invalid media type
855 if(!(inserted && check_media_type())) {
860 if(trk == -1 && side == -1) {
864 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
865 if(!(0 <= trkside && trkside < 164)) {
869 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
871 if(!IS_VALID_TRACK(offset.d)) {
876 uint8* t = buffer + offset.d;
877 sector_num.read_2bytes_le_from(t + 4);
879 if(index >= sector_num.sd) {
884 for(int i = 0; i < index; i++) {
886 data_size.read_2bytes_le_from(t + 14);
887 t += data_size.sd + 0x10;
893 void DISK::set_sector_info(uint8 *t)
901 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
902 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
903 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
904 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
905 id[4] = (crc >> 8) & 0xff;
906 id[5] = (crc >> 0) & 0xff;
907 // http://www,gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
908 // t[6]: 0x00 = double-density, 0x40 = single-density
909 // t[7]: 0x00 = normal, 0x10 = deleted mark
910 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
912 deleted = (t[7] != 0);
914 // if(ignore_crc()) {
915 // crc_error = false;
917 // crc_error = (((t[8] & 0xf0) != 0x00) && ((t[8] & 0xf0) != 0x10));
918 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
919 data_crc_error = ((t[8] & 0xf0) == 0xb0);
922 sector_size.read_2bytes_le_from(t + 14);
925 void DISK::set_deleted(bool value)
928 uint8 *t = sector - 0x10;
929 t[7] = value ? 0x10 : 0;
930 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
931 t[8] = (t[8] & 0x0f) | t[7];
937 void DISK::set_data_crc_error(bool value)
940 uint8 *t = sector - 0x10;
941 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
943 data_crc_error = value;
946 void DISK::set_data_mark_missing()
949 uint8 *t = sector - 0x10;
950 //t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]); // FIXME: always data crc error ?
951 t[8] = (t[8] & 0x0f) | 0xf0;
955 //addr_crc_error = value;
956 data_crc_error = false;
959 bool DISK::format_track(int trk, int side)
961 // disk not inserted or invalid media type
962 if(!(inserted && check_media_type())) {
967 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
968 if(!(0 <= trkside && trkside < 164)) {
972 // create new empty track
975 trim_required = false;
977 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
979 offset.d = DISK_BUFFER_SIZE;
980 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
982 trim_required = true;
984 track_mfm = drive_mfm;
989 void DISK::insert_sector(uint8 c, uint8 h, uint8 r, uint8 n, bool deleted, bool data_crc_error, uint8 fill_data, int length)
991 uint8* t = buffer + DISK_BUFFER_SIZE;
994 for(int i = 0; i < (sector_num.sd - 1); i++) {
995 t[4] = sector_num.b.l;
996 t[5] = sector_num.b.h;
998 data_size.read_2bytes_le_from(t + 14);
999 t += data_size.sd + 0x10;
1005 t[4] = sector_num.b.l;
1006 t[5] = sector_num.b.h;
1007 t[6] = track_mfm ? 0 : 0x40;
1008 t[7] = deleted ? 0x10 : 0;
1009 t[8] = data_crc_error ? 0xb0 : t[7];
1010 t[14] = (length >> 0) & 0xff;
1011 t[15] = (length >> 8) & 0xff;
1012 memset(t + 16, fill_data, length);
1017 void DISK::sync_buffer()
1021 trim_required = false;
1025 void DISK::trim_buffer()
1027 int max_tracks = 164;
1028 uint32 dest_offset = 0x2b0;
1031 memset(tmp_buffer, 0, sizeof(tmp_buffer));
1032 memcpy(tmp_buffer, buffer, 0x20);
1035 for(int trkside = 0; trkside < 164; trkside++) {
1036 pair src_trk_offset;
1037 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1038 if(src_trk_offset.d != 0) {
1040 if(src_trk_offset.d < 0x2b0) {
1041 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1044 if(src_trk_offset.d != 0x2b0) {
1045 max_tracks = (src_trk_offset.d - 0x20) >> 2;
1046 if(max_tracks > 164) {
1047 dest_offset = 0x20 + max_tracks * 4);
1056 for(int trkside = 0; trkside < max_tracks; trkside++) {
1057 pair src_trk_offset;
1058 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
1060 pair dest_trk_offset;
1061 dest_trk_offset.d = 0;
1063 if(IS_VALID_TRACK(src_trk_offset.d)) {
1064 uint8* t = buffer + src_trk_offset.d;
1065 pair sector_num, data_size;
1066 sector_num.read_2bytes_le_from(t + 4);
1067 if(sector_num.sd != 0) {
1068 dest_trk_offset.d = dest_offset;
1069 for(int i = 0; i < sector_num.sd; i++) {
1070 data_size.read_2bytes_le_from(t + 14);
1071 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
1072 dest_offset += data_size.sd + 0x10;
1073 t += data_size.sd + 0x10;
1077 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
1081 file_size.d = dest_offset;
1082 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
1084 memset(buffer, 0, sizeof(buffer));
1085 memcpy(buffer, tmp_buffer, min(sizeof(buffer), file_size.d));
1086 //memcpy(buffer, tmp_buffer, (file_size.d > sizeof(buffer)) ? sizeof(buffer) : file_size.d);
1091 if(drive_rpm != 0) {
1093 } else if(inserted) {
1094 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
1096 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
1100 int DISK::get_track_size()
1103 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1104 if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
1105 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3100;
1108 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : track_mfm ? 6250 : 3100;
1110 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1111 if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
1112 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3100;
1115 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
1119 double DISK::get_usec_per_track()
1121 return 1000000.0 / (get_rpm() / 60.0);
1124 double DISK::get_usec_per_bytes(int bytes)
1126 #if defined(_FM77AV_VARIANTS)
1127 if(is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE) {
1128 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0) * 2.2) * bytes;
1131 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
1134 int DISK::get_bytes_per_usec(double usec)
1136 return (int)(usec / get_usec_per_bytes(1) + 0.5);
1139 bool DISK::check_media_type()
1141 switch(drive_type) {
1143 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1144 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
1145 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1147 return (media_type == MEDIA_TYPE_2D);
1149 case DRIVE_TYPE_2DD:
1150 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
1151 case DRIVE_TYPE_2HD:
1152 return (media_type == MEDIA_TYPE_2HD);
1153 case DRIVE_TYPE_144:
1154 return (media_type == MEDIA_TYPE_144);
1155 case DRIVE_TYPE_UNK:
1156 return true; // always okay
1163 #define COPYBUFFER(src, size) { \
1164 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
1167 memcpy(buffer + file_size.d, (src), (size)); \
1168 file_size.d += (size); \
1183 uint8 dens, del, stat;
1188 // teledisk image decoder
1191 this teledisk image decoder is based on:
1193 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1194 LZSS coded by Haruhiko OKUMURA
1195 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1196 Edited and translated to English by Kenji RIKITAKE
1200 #define STRING_BUFFER_SIZE 4096
1201 #define LOOKAHEAD_BUFFER_SIZE 60
1203 #define N_CHAR (256 - THRESHOLD + LOOKAHEAD_BUFFER_SIZE)
1204 #define TABLE_SIZE (N_CHAR * 2 - 1)
1205 #define ROOT_POSITION (TABLE_SIZE - 1)
1206 #define MAX_FREQ 0x8000
1208 static uint8 td_text_buf[STRING_BUFFER_SIZE + LOOKAHEAD_BUFFER_SIZE - 1];
1209 static uint16 td_ptr;
1210 static uint16 td_bufcnt, td_bufndx, td_bufpos;
1211 static uint16 td_ibufcnt, td_ibufndx;
1212 static uint8 td_inbuf[512];
1213 static uint16 td_freq[TABLE_SIZE + 1];
1214 static short td_prnt[TABLE_SIZE + N_CHAR];
1215 static short td_son[TABLE_SIZE];
1216 static uint16 td_getbuf;
1217 static uint8 td_getlen;
1219 static const uint8 td_d_code[256] = {
1220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1223 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
1224 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1225 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1226 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1227 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
1228 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
1229 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
1230 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
1231 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
1232 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
1233 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
1234 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
1235 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
1237 static const uint8 td_d_len[256] = {
1238 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1239 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
1240 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1241 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1242 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
1243 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1244 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1245 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1246 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
1247 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1248 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1249 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
1250 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1251 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1252 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
1253 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
1256 static int td_next_word(FILEIO* fio)
1258 if(td_ibufndx >= td_ibufcnt) {
1259 td_ibufndx = td_ibufcnt = 0;
1260 memset(td_inbuf, 0, 512);
1261 for(int i = 0; i < 512; i++) {
1262 int d = fio->Fgetc();
1273 while(td_getlen <= 8) {
1274 td_getbuf |= td_inbuf[td_ibufndx++] << (8 - td_getlen);
1280 static int td_get_bit(FILEIO* fio)
1282 if(td_next_word(fio) < 0) {
1285 short i = td_getbuf;
1288 return (i < 0) ? 1 : 0;
1291 static int td_get_byte(FILEIO* fio)
1293 if(td_next_word(fio) != 0) {
1296 uint16 i = td_getbuf;
1303 static void td_start_huff()
1306 for(i = 0; i < N_CHAR; i++) {
1308 td_son[i] = i + TABLE_SIZE;
1309 td_prnt[i + TABLE_SIZE] = i;
1312 while(j <= ROOT_POSITION) {
1313 td_freq[j] = td_freq[i] + td_freq[i + 1];
1315 td_prnt[i] = td_prnt[i + 1] = j;
1318 td_freq[TABLE_SIZE] = 0xffff;
1319 td_prnt[ROOT_POSITION] = 0;
1322 static void td_reconst()
1326 for(i = 0; i < TABLE_SIZE; i++) {
1327 if(td_son[i] >= TABLE_SIZE) {
1328 td_freq[j] = (td_freq[i] + 1) / 2;
1329 td_son[j] = td_son[i];
1333 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1335 f = td_freq[j] = td_freq[i] + td_freq[k];
1336 for(k = j - 1; f < td_freq[k]; k--);
1339 memmove(&td_freq[k + 1], &td_freq[k], l);
1341 memmove(&td_son[k + 1], &td_son[k], l);
1344 for(i = 0; i < TABLE_SIZE; i++) {
1345 if((k = td_son[i]) >= TABLE_SIZE) {
1348 td_prnt[k] = td_prnt[k + 1] = i;
1353 static void td_update(int c)
1356 if(td_freq[ROOT_POSITION] == MAX_FREQ) {
1359 c = td_prnt[c + TABLE_SIZE];
1362 if(k > td_freq[l = c + 1]) {
1363 while(k > td_freq[++l]);
1365 td_freq[c] = td_freq[l];
1369 if(i < TABLE_SIZE) {
1375 if(j < TABLE_SIZE) {
1382 while((c = td_prnt[c]) != 0);
1385 static short td_decode_char(FILEIO* fio)
1388 uint16 c = td_son[ROOT_POSITION];
1389 while(c < TABLE_SIZE) {
1390 if((ret = td_get_bit(fio)) < 0) {
1401 static short td_decode_position(FILEIO* fio)
1405 if((bit = td_get_byte(fio)) < 0) {
1409 c = (uint16)td_d_code[i] << 6;
1410 j = td_d_len[i] - 2;
1412 if((bit = td_get_bit(fio)) < 0) {
1417 return (c | i & 0x3f);
1420 static void td_init_decode()
1422 td_ibufcnt= td_ibufndx = td_bufcnt = td_getbuf = 0;
1425 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1426 td_text_buf[i] = ' ';
1428 td_ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1431 static int td_decode(FILEIO* fio, uint8 *buf, int len)
1435 for(count = 0; count < len;) {
1436 if(td_bufcnt == 0) {
1437 if((c = td_decode_char(fio)) < 0) {
1441 *(buf++) = (uint8)c;
1442 td_text_buf[td_ptr++] = (uint8)c;
1443 td_ptr &= (STRING_BUFFER_SIZE - 1);
1446 if((pos = td_decode_position(fio)) < 0) {
1449 td_bufpos = (td_ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1450 td_bufcnt = c - 255 + THRESHOLD;
1454 while(td_bufndx < td_bufcnt && count < len) {
1455 c = td_text_buf[(td_bufpos + td_bufndx) & (STRING_BUFFER_SIZE - 1)];
1456 *(buf++) = (uint8)c;
1458 td_text_buf[td_ptr++] = (uint8)c;
1459 td_ptr &= (STRING_BUFFER_SIZE - 1);
1462 if(td_bufndx >= td_bufcnt) {
1463 td_bufndx = td_bufcnt = 0;
1490 uint8 nsec, trk, head;
1499 bool DISK::teledisk_to_d88(FILEIO *fio)
1506 bool temporary = false;
1508 // check teledisk header
1509 fio->Fseek(0, FILEIO_SEEK_SET);
1510 fio->Fread(&hdr, sizeof(td_hdr_t), 1);
1511 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1512 // this image is compressed
1513 // decompress to the temporary file
1514 FILEIO* fio_tmp = new FILEIO();
1515 if(!fio_tmp->Fopen(local_path(_T("teledisk.$$$")), FILEIO_WRITE_BINARY)) {
1522 if((rd = td_decode(fio, obuf, 512)) > 0) {
1523 fio_tmp->Fwrite(obuf, rd, 1);
1531 // reopen the temporary file
1533 if(!fio->Fopen(_T("teledisk.$$$"), FILEIO_READ_BINARY)) {
1536 } else if(hdr.sig[0] == 'T' && hdr.sig[1] == 'D') {
1537 // this image is not compressed
1541 if(hdr.flag & 0x80) {
1543 fio->Fread(&cmt, sizeof(td_cmt_t), 1);
1544 fio->Fseek(cmt.len, FILEIO_SEEK_CUR);
1547 // create d88 header
1551 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1552 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1553 //strncpy(d88_hdr.title, "TELEDISK", sizeof(d88_hdr.title));
1554 d88_hdr.protect = 0; // non-protected
1557 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1560 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1561 fio->Fread(&trk, sizeof(td_trk_t), 1);
1562 while(trk.nsec != 0xff) {
1563 d88_hdr.trkptr[trkcnt++] = trkptr;
1564 if(hdr.sides == 1) {
1568 // read sectors in this track
1569 for(int i = 0; i < trk.nsec; i++) {
1570 uint8 buf[2048], dst[2048];
1571 memset(buf, 0, sizeof(buf));
1572 memset(dst, 0, sizeof(dst));
1574 // read sector header
1575 fio->Fread(&sct, sizeof(td_sct_t), 1);
1577 // create d88 sector header
1578 memset(&d88_sct, 0, sizeof(d88_sct_t));
1583 d88_sct.nsec = trk.nsec;
1584 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1585 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1586 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1587 d88_sct.size = secsize[sct.n & 3];
1589 // create sector image
1590 if(sct.ctrl & 0x30) {
1591 d88_sct.stat = 0xf0; // data mark missing
1594 // read sector source
1595 int len = fio->Fgetc();
1596 len += fio->Fgetc() * 256 - 1;
1597 int flag = fio->Fgetc(), d = 0;
1598 fio->Fread(buf, len, 1);
1602 memcpy(dst, buf, len);
1603 } else if(flag == 1) {
1605 len2.read_2bytes_le_from(buf);
1610 } else if(flag == 2) {
1611 for(int s = 0; s < len;) {
1612 int type = buf[s++];
1613 int len2 = buf[s++];
1616 dst[d++] = buf[s++];
1618 } else if(type < 5) {
1624 for(int j = 0; j < n; j++) {
1628 for(int j = 0; j < n; j++) {
1633 break; // unknown type
1637 break; // unknown flag
1642 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1643 COPYBUFFER(dst, d88_sct.size);
1644 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1647 fio->Fread(&trk, sizeof(td_trk_t), 1);
1649 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 45) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1650 d88_hdr.size = trkptr;
1651 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1654 FILEIO::RemoveFile(_T("teledisk.$$$"));
1659 // imagedisk image decoder (from MESS formats/imd_dsk.c by Mr.Miodrag Milanovic)
1661 bool DISK::imagedisk_to_d88(FILEIO *fio)
1663 //d88_hdr_t d88_hdr;
1664 //d88_sct_t d88_sct;
1665 int size = fio->FileLength();
1666 fio->Fseek(0, FILEIO_SEEK_SET);
1667 fio->Fread(tmp_buffer, size, 1);
1669 if(memcmp(tmp_buffer, "IMD ", 4) != 0) {
1674 for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
1681 // create d88 header
1685 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1686 //strncpy(d88_hdr.title, "IMAGEDISK", sizeof(d88_hdr.title));
1687 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
1688 d88_hdr.protect = 0; // non-protected
1691 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1694 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1699 //for(pos = 0; pos < size && tmp_buffer[pos] != 0x1a; pos++);
1703 // check track header
1704 uint8 mode = tmp_buffer[pos++];
1705 uint8 track = tmp_buffer[pos++];
1706 uint8 head = tmp_buffer[pos++];
1707 uint8 sector_count = tmp_buffer[pos++];
1708 uint8 ssize = tmp_buffer[pos++];
1710 if(sector_count == 0) {
1716 uint32 actual_size = ssize < 7 ? 128 << ssize : 8192;
1719 const uint8 *snum = &tmp_buffer[pos];
1720 pos += sector_count;
1721 const uint8 *tnum = head & 0x80 ? &tmp_buffer[pos] : NULL;
1723 pos += sector_count;
1724 const uint8 *hnum = head & 0x40 ? &tmp_buffer[pos] : NULL;
1726 pos += sector_count;
1730 int trkside = track * 2 + (head & 1);
1732 if(trkcnt < trkside) {
1735 d88_hdr.trkptr[trkside] = trkptr;
1737 if(img_mode == -1) {
1738 img_mode = mode & 3;
1741 // read sectors in this track
1742 for(int i = 0; i < sector_count; i++) {
1743 // create d88 sector header
1744 uint8 stype = tmp_buffer[pos++];
1745 memset(&d88_sct, 0, sizeof(d88_sct_t));
1746 d88_sct.c = tnum ? tnum[i] : track;
1747 d88_sct.h = hnum ? hnum[i] : head;
1748 d88_sct.r = snum[i];
1750 d88_sct.nsec = sector_count;
1751 d88_sct.dens = (mode < 3) ? 0x40 : 0;
1753 if(stype == 0 || stype > 8) {
1754 d88_sct.stat = 0xf0; // data mark missing
1757 d88_sct.del = (stype == 3 || stype == 4 || stype == 7 || stype == 8) ? 0x10 : 0;
1758 d88_sct.stat = (stype == 5 || stype == 6 || stype == 7 || stype == 8) ? 0xb0 : d88_sct.del;
1759 d88_sct.size = actual_size;
1761 // create sector image
1762 if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
1763 memset(dst, tmp_buffer[pos++], actual_size);
1765 memcpy(dst, &tmp_buffer[pos], actual_size);
1766 pos += d88_sct.size;
1772 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1773 COPYBUFFER(dst, d88_sct.size);
1774 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1778 d88_hdr.type = (img_mode == 0) ? MEDIA_TYPE_2HD : (((trkcnt + 1) >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1779 d88_hdr.size = trkptr;
1780 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1784 // cpdread image decoder (from MESS formats/dsk_dsk.c by Mr.Olivier Galibert)
1786 #define DSK_FORMAT_HEADER "MV - CPC"
1787 #define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
1790 struct track_header {
1791 uint8 headertag[13];
1798 uint8 sector_size_code;
1799 uint8 number_of_sector;
1803 struct sector_header {
1807 uint8 sector_size_code;
1808 uint8 fdc_status_reg1;
1809 uint8 fdc_status_reg2;
1814 bool DISK::cpdread_to_d88(FILEIO *fio)
1816 bool extendformat = false;
1817 int image_size = fio->FileLength();
1819 fio->Fseek(0, FILEIO_SEEK_SET);
1820 fio->Fread(tmp_buffer, image_size, 1);
1822 if(memcmp(tmp_buffer, EXT_FORMAT_HEADER, 16) == 0) {
1823 extendformat = true;
1824 } else if(memcmp(tmp_buffer, DSK_FORMAT_HEADER, 8) == 0) {
1825 extendformat = false;
1830 int heads = tmp_buffer[0x31];
1835 int tracks = tmp_buffer[0x30];
1836 int track_offsets[84 * 2];
1837 bool track_offsets_error = false;
1839 int cnt = 0, tmp = 0x100;
1840 for(int i = 0; i < tracks * heads; i++) {
1841 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1844 track_offsets[cnt] = tmp;
1845 tmp += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
1849 int cnt = 0, tmp = 0x100;
1850 for(int i = 0; i < tracks * heads; i++) {
1851 int length = tmp_buffer[0x34 + i] << 8;
1853 if(track_offsets_error = (memcmp(tmp_buffer + tmp, "Track-Info", 10) != 0)) {
1856 track_offsets[cnt] = tmp;
1859 track_offsets[cnt] = image_size;
1864 if(track_offsets_error) {
1865 // I found the dsk image that the track size in table is 1100h, but the actual track size is 900h,
1866 // so I modified this code to search "Track-Info" at the top of track information block
1867 int cnt = 0, tmp = 0x100;
1868 for(int i = 0; i < tracks * heads; i++) {
1870 for(; tmp < image_size; tmp += 0x10) {
1871 if(found = (memcmp(tmp_buffer + tmp, "Track-Info", 10) == 0)) {
1876 track_offsets[cnt] = tmp;
1879 track_offsets[cnt] = image_size;
1885 // create d88 header
1889 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1890 //strncpy(d88_hdr.title, "CPDREAD", sizeof(d88_hdr.title));
1891 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDREAD");
1892 d88_hdr.protect = 0; // non-protected
1895 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1898 int total = 0, trkptr = sizeof(d88_hdr_t);
1900 for(int track = 0; track < tracks; track++) {
1901 for(int side = 0; side < heads; side++) {
1902 if(track_offsets[(track << 1) + side] >= image_size) {
1905 if((track << 1) + side < 164) {
1906 d88_hdr.trkptr[(track << 1) + side] = trkptr;
1910 memcpy(&tr, tmp_buffer + track_offsets[(track << 1) + side], sizeof(tr));
1911 int pos = track_offsets[(track << 1) + side] + 0x100;
1912 for(int j = 0; j < tr.number_of_sector; j++) {
1913 sector_header sector;
1914 memcpy(§or, tmp_buffer + track_offsets[(track << 1) + side] + sizeof(tr) + (sizeof(sector) * j), sizeof(sector));
1916 // create d88 sector header
1917 memset(&d88_sct, 0, sizeof(d88_sct_t));
1918 d88_sct.c = sector.track;
1919 d88_sct.h = sector.side;
1920 d88_sct.r = sector.sector_id;
1921 d88_sct.n = sector.sector_size_code;
1922 d88_sct.nsec = tr.number_of_sector;
1924 d88_sct.size = sector.data_length;
1925 d88_sct.dens = (tr.rec_mode == 1) ? 0x40 : 0;
1927 d88_sct.size = 128 << tr.sector_size_code;
1928 d88_sct.dens = (tr.sector_size_code == 0) ? 0x40 : 0; // FIXME
1930 d88_sct.del = (sector.fdc_status_reg1 == 0xb2) ? 0x10 : 0;
1931 d88_sct.stat = (d88_sct.size == 0) ? 0xf0 : (sector.fdc_status_reg1 == 0xb5) ? 0xb0 : d88_sct.del;
1934 if((track << 1) + side < 164) {
1935 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1936 COPYBUFFER(tmp_buffer + pos, d88_sct.size);
1937 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1939 total += d88_sct.size;
1942 pos += sector.data_length;
1944 pos += 128 << tr.sector_size_code;
1949 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
1950 d88_hdr.size = trkptr;
1951 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1955 // solid image decoder
1957 bool DISK::solid_to_d88(FILEIO *fio, int type, int ncyl, int nside, int nsec, int size, bool mfm)
1963 solid_nside = nside;
1968 // create d88 header
1972 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1973 //strncpy(d88_hdr.title, "SOLID", sizeof(d88_hdr.title));
1974 my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "SOLID");
1975 d88_hdr.protect = 0; // non-protected
1978 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1981 for(int i = 0; i < 8; i++) {
1982 if(size == (128 << i)) {
1989 int trkptr = sizeof(d88_hdr_t);
1991 for(int c = 0; c < ncyl; c++) {
1992 for(int h = 0; h < nside; h++) {
1993 d88_hdr.trkptr[t++] = trkptr;
1998 // read sectors in this track
1999 for(int s = 0; s < nsec; s++) {
2000 // create d88 sector header
2001 memset(&d88_sct, 0, sizeof(d88_sct_t));
2006 d88_sct.nsec = nsec;
2010 d88_sct.size = size;
2012 // create sector image
2014 memset(dst, 0xe5, sizeof(dst));
2015 fio->Fread(dst, size, 1);
2018 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
2019 COPYBUFFER(dst, size);
2020 trkptr += sizeof(d88_sct_t) + size;
2024 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
2025 d88_hdr.size = trkptr;
2026 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
2030 #define STATE_VERSION 10
2032 void DISK::save_state(FILEIO* state_fio)
2034 state_fio->FputUint32(STATE_VERSION);
2036 state_fio->Fwrite(buffer, sizeof(buffer), 1);
2037 state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
2038 state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
2039 state_fio->FputUint32(file_size.d);
2040 state_fio->FputInt32(file_bank);
2041 state_fio->FputUint32(crc32);
2042 state_fio->FputBool(trim_required);
2043 state_fio->FputBool(is_1dd_image);
2044 state_fio->FputBool(is_solid_image);
2045 state_fio->FputBool(is_fdi_image);
2046 state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
2047 state_fio->FputInt32(solid_ncyl);
2048 state_fio->FputInt32(solid_nside);
2049 state_fio->FputInt32(solid_nsec);
2050 state_fio->FputInt32(solid_size);
2051 state_fio->FputBool(solid_mfm);
2052 state_fio->FputBool(inserted);
2053 state_fio->FputBool(ejected);
2054 state_fio->FputBool(write_protected);
2055 state_fio->FputBool(changed);
2056 state_fio->FputUint8(media_type);
2057 state_fio->FputInt32(is_special_disk);
2058 state_fio->Fwrite(track, sizeof(track), 1);
2059 state_fio->FputInt32(sector_num.sd);
2060 state_fio->FputBool(track_mfm);
2061 state_fio->FputBool(invalid_format);
2062 // state_fio->FputBool(no_skew);
2063 state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
2064 state_fio->Fwrite(am1_position, sizeof(am1_position), 1);
2065 state_fio->Fwrite(id_position, sizeof(id_position), 1);
2066 state_fio->Fwrite(data_position, sizeof(data_position), 1);
2067 state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
2068 state_fio->FputInt32(sector_size.sd);
2069 state_fio->Fwrite(id, sizeof(id), 1);
2070 state_fio->FputUint8(density);
2071 state_fio->FputBool(deleted);
2072 state_fio->FputBool(addr_crc_error);
2073 state_fio->FputBool(data_crc_error);
2074 state_fio->FputUint8(drive_type);
2075 state_fio->FputInt32(drive_rpm);
2076 state_fio->FputBool(drive_mfm);
2079 bool DISK::load_state(FILEIO* state_fio)
2081 if(state_fio->FgetUint32() != STATE_VERSION) {
2084 state_fio->Fread(buffer, sizeof(buffer), 1);
2085 state_fio->Fread(orig_path, sizeof(orig_path), 1);
2086 state_fio->Fread(dest_path, sizeof(dest_path), 1);
2087 file_size.d = state_fio->FgetUint32();
2088 file_bank = state_fio->FgetInt32();
2089 crc32 = state_fio->FgetUint32();
2090 trim_required = state_fio->FgetBool();
2091 is_1dd_image = state_fio->FgetBool();
2092 is_solid_image = state_fio->FgetBool();
2093 is_fdi_image = state_fio->FgetBool();
2094 state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
2095 solid_ncyl = state_fio->FgetInt32();
2096 solid_nside = state_fio->FgetInt32();
2097 solid_nsec = state_fio->FgetInt32();
2098 solid_size = state_fio->FgetInt32();
2099 solid_mfm = state_fio->FgetBool();
2100 inserted = state_fio->FgetBool();
2101 ejected = state_fio->FgetBool();
2102 write_protected = state_fio->FgetBool();
2103 changed = state_fio->FgetBool();
2104 media_type = state_fio->FgetUint8();
2105 is_special_disk = state_fio->FgetInt32();
2106 state_fio->Fread(track, sizeof(track), 1);
2107 sector_num.sd = state_fio->FgetInt32();
2108 track_mfm = state_fio->FgetBool();
2109 invalid_format = state_fio->FgetBool();
2110 // no_skew = state_fio->FgetBool();
2111 state_fio->Fread(sync_position, sizeof(sync_position), 1);
2112 state_fio->Fread(am1_position, sizeof(am1_position), 1);
2113 state_fio->Fread(id_position, sizeof(id_position), 1);
2114 state_fio->Fread(data_position, sizeof(data_position), 1);
2115 int offset = state_fio->FgetInt32();
2116 sector = (offset != -1) ? buffer + offset : NULL;
2117 sector_size.sd = state_fio->FgetInt32();
2118 state_fio->Fread(id, sizeof(id), 1);
2119 density = state_fio->FgetUint8();
2120 deleted = state_fio->FgetBool();
2121 addr_crc_error = state_fio->FgetBool();
2122 data_crc_error = state_fio->FgetBool();
2123 drive_type = state_fio->FgetUint8();
2124 drive_rpm = state_fio->FgetInt32();
2125 drive_mfm = state_fio->FgetBool();