2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 #include "../config.h"
14 static const uint16 crc_table[256] = {
15 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
16 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
17 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
18 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
19 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
20 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
21 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
22 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
23 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
24 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
25 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
26 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
27 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
28 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
29 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
30 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
33 // teledisk decoder table
34 static const uint8 d_code[256] = {
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
38 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
39 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
40 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
41 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
42 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
43 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
44 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
45 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
46 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
47 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
48 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
49 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f,
50 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
52 static const uint8 d_len[256] = {
53 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
54 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
55 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
56 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
57 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
58 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
59 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
60 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
61 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
62 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
63 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
64 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
65 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
66 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
67 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
68 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
70 static const int secsize[8] = {
71 128, 256, 512, 1024, 2048, 4096, 8192, 16384
74 static uint8 tmp_buffer[DISK_BUFFER_SIZE];
78 int ncyl, nside, nsec, size;
81 static const fd_format_t fd_formats[] = {
82 { MEDIA_TYPE_2D, 40, 1, 16, 256 }, // 1D 160KB
83 #if defined(SUPPORT_MEDIA_TYPE_1DD)
84 { MEDIA_TYPE_2DD, 80, 1, 16, 256 }, // 1DD 320KB
85 { MEDIA_TYPE_2DD, 80, 1, 9, 512 }, // 1DD 360KB
87 { MEDIA_TYPE_2D , 40, 2, 16, 256 }, // 2D 320KB
88 { MEDIA_TYPE_2D, 40, 2, 9, 512 }, // 2D 360KB
90 #if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200) || defined(_MZ2500)
91 { MEDIA_TYPE_2DD, 80, 2, 16, 256 }, // 2DD 640KB (MZ-2500)
93 { MEDIA_TYPE_2DD, 80, 2, 8, 512 }, // 2DD 640KB
95 { MEDIA_TYPE_2DD, 80, 2, 9, 512 }, // 2DD 720KB
96 #if defined(_PX7) || defined(_MSX1) || defined(_MSX2)
97 { MEDIA_TYPE_2DD, 81, 2, 9, 512 }, // 2DD 729KB
99 { MEDIA_TYPE_2HD, 80, 2, 15, 512 }, // 2HC 1.20MB
100 { MEDIA_TYPE_2HD, 77, 2, 8, 1024 }, // 2HD 1.25MB
101 { MEDIA_TYPE_144, 80, 2, 18, 512 }, // 2HD 1.44MB
102 { MEDIA_TYPE_144, 80, 2, 36, 512 }, // 2ED 2.88MB
106 #define IS_VALID_TRACK(offset) ((offset) >= 0x20 && (offset) < sizeof(buffer))
108 void DISK::open(_TCHAR path[], int bank)
110 // check current disk image
112 if(_tcsicmp(orig_path, path) == 0 && file_bank == bank) {
117 memset(buffer, 0, sizeof(buffer));
118 media_type = MEDIA_TYPE_UNK;
119 is_solid_image = is_fdi_image = is_1dd_image = false;
120 trim_required = false;
124 if(fi->Fopen(path, FILEIO_READ_BINARY)) {
125 bool converted = false;
127 _tcscpy_s(orig_path, _MAX_PATH, path);
128 _tcscpy_s(dest_path, _MAX_PATH, path);
129 _stprintf_s(temp_path, _MAX_PATH, _T("%s.$$$"), path);
132 write_protected = false; //FILEIO::IsFileProtected(path);
134 // is this d88 format ?
135 if(check_file_extension(path, _T(".d88")) || check_file_extension(path, _T(".d77")) || check_file_extension(path, _T(".1dd"))) {
137 for(int i = 0; i < bank; i++) {
138 fi->Fseek(offset + 0x1c, SEEK_SET);
139 offset += fi->FgetUint32_LE();
141 fi->Fseek(offset + 0x1c, FILEIO_SEEK_SET);
142 file_size.d = fi->FgetUint32_LE();
143 fi->Fseek(offset, FILEIO_SEEK_SET);
144 fi->Fread(buffer, file_size.d, 1);
146 inserted = changed = true;
147 is_1dd_image = check_file_extension(path, _T(".1dd"));
148 // trim_required = true;
150 // fix sector number from big endian to little endian
151 for(int trkside = 0; trkside < 164; trkside++) {
153 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
155 if(!IS_VALID_TRACK(offset.d)) {
158 uint8* t = buffer + offset.d;
159 pair sector_num, data_size;
160 sector_num.read_2bytes_le_from(t + 4);
161 bool is_be = (sector_num.b.l == 0 && sector_num.b.h >= 4);
163 sector_num.read_2bytes_be_from(t + 4);
164 sector_num.write_2bytes_le_to(t + 4);
166 for(int i = 0; i < sector_num.sd; i++) {
168 sector_num.write_2bytes_le_to(t + 4);
170 data_size.read_2bytes_le_from(t + 14);
171 t += data_size.sd + 0x10;
177 fi->Fseek(0, FILEIO_SEEK_END);
178 file_size.d = fi->Ftell();
179 fi->Fseek(0, FILEIO_SEEK_SET);
182 #if defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
183 // is this 2d format ?
184 if(check_file_extension(path, _T(".2d"))) {
185 if(solid_to_d88(MEDIA_TYPE_2D, 40, 2, 16, 256)) {
186 inserted = changed = is_solid_image = true;
189 fi->Fseek(0, FILEIO_SEEK_SET);
193 // check image file format
194 for(int i = 0;; i++) {
195 const fd_format_t *p = &fd_formats[i];
199 int len = p->ncyl * p->nside * p->nsec * p->size;
200 // 4096 bytes: FDI header ???
201 if(file_size.d == len || (file_size.d == (len + 4096) && (len == 655360 || len == 1261568))) {
202 if(file_size.d == len + 4096) {
204 fi->Fread(fdi_header, 4096, 1);
206 if(solid_to_d88(p->type, p->ncyl, p->nside, p->nsec, p->size)) {
207 inserted = changed = is_solid_image = true;
212 if(0 < file_size.d && file_size.d <= DISK_BUFFER_SIZE) {
213 memset(buffer, 0, sizeof(buffer));
214 fi->Fread(buffer, file_size.d, 1);
216 // check d88 format (temporary)
217 if(file_size.b.l == buffer[0x1c] && file_size.b.h == buffer[0x1d] && file_size.b.h2 == buffer[0x1e] && file_size.b.h3 == buffer[0x1f]) {
218 inserted = changed = true;
221 _stprintf_s(dest_path, _MAX_PATH, _T("%s.D88"), path);
225 if(memcmp(buffer, "TD", 2) == 0 || memcmp(buffer, "td", 2) == 0) {
226 // teledisk image file
227 inserted = changed = converted = teledisk_to_d88();
228 } else if(memcmp(buffer, "IMD", 3) == 0) {
229 // imagedisk image file
230 inserted = changed = converted = imagedisk_to_d88();
231 } else if(memcmp(buffer, "MV - CPC", 8) == 0) {
232 // standard cpdread image file
233 inserted = changed = converted = cpdread_to_d88(0);
234 } else if(memcmp(buffer, "EXTENDED", 8) == 0) {
235 // extended cpdread image file
236 inserted = changed = converted = cpdread_to_d88(1);
239 // failed to convert the disk image
247 FILEIO::RemoveFile(temp_path);
250 if(buffer[0x1a] != 0) {
252 write_protected = true;
257 FILEIO* fio = new FILEIO();
258 if(fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
259 fio->Fwrite(buffer, file_size.d, 1);
265 crc32 = getcrc32(buffer, file_size.d);
267 if(media_type == MEDIA_TYPE_UNK) {
269 media_type = MEDIA_TYPE_2DD;
270 } else if((media_type = buffer[0x1b]) == MEDIA_TYPE_2HD) {
271 for(int trkside = 0; trkside < 164; trkside++) {
273 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
275 if(!IS_VALID_TRACK(offset.d)) {
279 uint8 *t = buffer + offset.d;
280 pair sector_num, data_size;
281 sector_num.read_2bytes_le_from(t + 4);
282 data_size.read_2bytes_le_from(t + 14);
284 if(sector_num.sd >= 18 && data_size.sd == 512) {
285 media_type = MEDIA_TYPE_144;
292 #if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
293 // FIXME: ugly patch for FM-7 Gambler Jiko Chuushin Ha
294 if(media_type == MEDIA_TYPE_2D) {
296 pair offset, sector_num, data_size;
297 offset.read_4bytes_le_from(buffer + 0x20);
298 if(IS_VALID_TRACK(offset.d)) {
299 // check the sector (c,h,r,n)=(0,0,7,1)
300 uint8* t = buffer + offset.d;
301 sector_num.read_2bytes_le_from(t + 4);
302 for(int i = 0; i < sector_num.sd; i++) {
303 data_size.read_2bytes_le_from(t + 14);
304 if(data_size.sd == 0x100 && t[0] == 0 && t[1] == 0 && t[2] == 7 && t[3] == 1) {
305 static const uint8 gambler[] = {0xb7, 0xde, 0xad, 0xdc, 0xdd, 0xcc, 0xde, 0xd7, 0xb1, 0x20, 0xbc, 0xde, 0xba, 0xc1, 0xad, 0xb3, 0xbc, 0xdd, 0xca};
306 if(memcmp((void *)(t + 0x30), gambler, sizeof(gambler)) == 0) {
307 is_special_disk = SPECIAL_DISK_FM7_GAMBLER;
311 t += data_size.sd + 0x10;
313 if(is_special_disk == 0) {
314 t = buffer + offset.d;
315 sector_num.read_2bytes_le_from(t + 4);
317 for(int i = 0; i < sector_num.sd; i++) {
318 data_size.read_2bytes_le_from(t + 14);
319 // FIXME : Check DEATH FORCE
320 if(data_size.sd == 0x200 && t[0] == 0 && t[1] == 0 && t[2] == 0xf7 && t[3] == 0x02) {
321 static const uint8 deathforce[] ={
322 0x44, 0x45, 0x41, 0x54, 0x48, 0x46, 0x4f, 0x52,
323 0x43, 0x45, 0x2f, 0x37, 0x37, 0x41, 0x56, 0xf7,
324 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
325 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
326 0x00, 0x00}; //"DEATHFORCE/77AV" + $f7*17 + $00 + $00
327 if(memcmp((void *)(t + 0x10), deathforce, sizeof(deathforce)) == 0) {
328 is_special_disk = SPECIAL_DISK_FM7_DEATHFORCE;
332 t += data_size.sd + 0x10;
337 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
338 // FIXME: ugly patch for X1turbo ALPHA and X1 Batten Tanuki
339 if(media_type == MEDIA_TYPE_2D) {
342 offset.read_4bytes_le_from(buffer + 0x20);
343 if(IS_VALID_TRACK(offset.d)) {
344 // check first sector
345 static const uint8 batten[] = {0xca, 0xde, 0xaf, 0xc3, 0xdd, 0x20, 0xc0, 0xc7, 0xb7};
346 uint8 *t = buffer + offset.d;
347 #if defined(_X1TURBO) || defined(_X1TURBOZ)
348 // if(strncmp((char *)(t + 0x11), "turbo ALPHA", 11) == 0) {
349 // is_special_disk = SPECIAL_DISK_X1TURBO_ALPHA;
352 if(memcmp((void *)(t + 0x11), batten, sizeof(batten)) == 0) {
353 is_special_disk = SPECIAL_DISK_X1_BATTEN;
368 trim_required = false;
370 buffer[0x1a] = write_protected ? 0x10 : 0; // mey be changed
372 if(/*!write_protected &&*/ file_size.d && getcrc32(buffer, file_size.d) != crc32) {
374 FILEIO* fio = new FILEIO();
375 int pre_size = 0, post_size = 0;
376 uint8 *pre_buffer = NULL, *post_buffer = NULL;
378 // is this d88 format ?
379 if(check_file_extension(dest_path, _T(".d88")) || check_file_extension(dest_path, _T(".d77")) || check_file_extension(dest_path, _T(".1dd"))) {
380 if(fio->Fopen(dest_path, FILEIO_READ_BINARY)) {
381 fio->Fseek(0, FILEIO_SEEK_END);
382 uint32 total_size = fio->Ftell(), offset = 0;
383 for(int i = 0; i < file_bank; i++) {
384 fio->Fseek(offset + 0x1c, SEEK_SET);
385 offset += fio->FgetUint32_LE();
387 if((pre_size = offset) > 0) {
388 pre_buffer = (uint8 *)malloc(pre_size);
389 fio->Fseek(0, FILEIO_SEEK_SET);
390 fio->Fread(pre_buffer, pre_size, 1);
392 fio->Fseek(offset + 0x1c, SEEK_SET);
393 offset += fio->FgetUint32_LE();
394 if((post_size = total_size - offset) > 0) {
395 post_buffer = (uint8 *)malloc(post_size);
396 fio->Fseek(offset, FILEIO_SEEK_SET);
397 fio->Fread(post_buffer, post_size, 1);
402 if((FILEIO::IsFileExists(dest_path) && FILEIO::IsFileProtected(dest_path)) || !fio->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
403 _TCHAR tmp_path[_MAX_PATH];
404 _stprintf_s(tmp_path, _MAX_PATH, _T("temporary_saved_floppy_disk_#%d.d88"), drive_num);
405 fio->Fopen(emu->bios_path(tmp_path), FILEIO_WRITE_BINARY);
407 if(fio->IsOpened()) {
409 fio->Fwrite(pre_buffer, pre_size, 1);
413 fio->Fwrite(fdi_header, 4096, 1);
415 for(int trkside = 0; trkside < 164; trkside++) {
417 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
419 if(!IS_VALID_TRACK(offset.d)) {
422 uint8* t = buffer + offset.d;
423 pair sector_num, data_size;
424 sector_num.read_2bytes_le_from(t + 4);
426 for(int i = 0; i < sector_num.sd; i++) {
427 data_size.read_2bytes_le_from(t + 14);
428 fio->Fwrite(t + 0x10, data_size.sd, 1);
429 t += data_size.sd + 0x10;
433 fio->Fwrite(buffer, file_size.d, 1);
436 fio->Fwrite(post_buffer, post_size, 1);
450 inserted = write_protected = false;
452 sector_size.sd = sector_num.sd = 0;
456 bool DISK::get_track(int trk, int side)
458 sector_size.sd = sector_num.sd = 0;
459 invalid_format = false;
462 // disk not inserted or invalid media type
463 if(!(inserted && check_media_type())) {
468 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
469 if(!(0 <= trkside && trkside < 164)) {
474 if(media_type == MEDIA_TYPE_2D) {
475 if((drive_type == DRIVE_TYPE_2DD) ||
476 (drive_type == DRIVE_TYPE_2HD) ||
477 (drive_type == DRIVE_TYPE_144)) {
479 for(int i = 0; i < get_track_size(); i++) {
484 cur_track = cur_track >> 1;
489 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
491 if(!IS_VALID_TRACK(offset.d)) {
496 sector = buffer + offset.d;
497 sector_num.read_2bytes_le_from(sector + 4);
499 data_size.read_2bytes_le_from(sector + 14);
501 // create each sector position in track
502 int sync_size = drive_mfm ? 12 : 6;
503 int am_size = drive_mfm ? 3 : 0;
504 int gap0_size = drive_mfm ? 80 : 40;
505 int gap1_size = drive_mfm ? 50 : 26;
506 int gap2_size = drive_mfm ? 22 : 11;
507 int gap3_size = 0, gap4_size;
509 if(media_type == MEDIA_TYPE_144 || media_type == MEDIA_TYPE_2HD) {
511 if(data_size.sd == 256 && sector_num.sd == 26) gap3_size = 54;
512 if(data_size.sd == 512 && sector_num.sd == 15) gap3_size = 84;
513 if(data_size.sd == 1024 && sector_num.sd == 8) gap3_size = 116;
515 if(data_size.sd == 128 && sector_num.sd == 26) gap3_size = 27;
516 if(data_size.sd == 256 && sector_num.sd == 15) gap3_size = 42;
517 if(data_size.sd == 512 && sector_num.sd == 8) gap3_size = 58;
521 if(data_size.sd == 256 && sector_num.sd == 16) gap3_size = 51;
522 if(data_size.sd == 512 && sector_num.sd == 9) gap3_size = 80;
523 if(data_size.sd == 1024 && sector_num.sd == 5) gap3_size = 116;
525 if(data_size.sd == 128 && sector_num.sd == 16) gap3_size = 27;
526 if(data_size.sd == 256 && sector_num.sd == 9) gap3_size = 42;
527 if(data_size.sd == 512 && sector_num.sd == 5) gap3_size = 58;
532 int total = sync_size + (am_size + 1);
534 for(int i = 0; i < sector_num.sd; i++) {
535 data_size.read_2bytes_le_from(t + 14);
536 total += sync_size + (am_size + 1) + (4 + 2) + gap2_size;
537 if(data_size.sd > 0) {
538 total += sync_size + (am_size + 1);
539 total += data_size.sd + 2;
544 t += data_size.sd + 0x10;
547 gap3_size = (get_track_size() - total - gap0_size - gap1_size) / (sector_num.sd + 1);
549 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
551 if(gap3_size < 8 || gap4_size < 8) {
552 gap0_size = gap1_size = gap3_size = (get_track_size() - total) / (2 + sector_num.sd + 1);
553 gap4_size = get_track_size() - total - gap0_size - gap1_size - gap3_size * sector_num.sd;
555 if(gap3_size < 8 || gap4_size < 8) {
556 gap0_size = gap1_size = gap3_size = gap4_size = 32;
557 invalid_format = true;
559 int preamble_size = gap0_size + sync_size + (am_size + 1) + gap1_size;
562 total = preamble_size;
563 sync_position[array_length(sync_position) - 1] = gap0_size; // sync position in preamble
565 for(int i = 0; i < sector_num.sd; i++) {
566 data_size.read_2bytes_le_from(t + 14);
568 total = preamble_size + (get_track_size() - preamble_size - gap4_size) * i / sector_num.sd;
570 sync_position[i] = total;
571 total += sync_size + (am_size + 1);
572 id_position[i] = total;
573 total += (4 + 2) + gap2_size;
574 if(data_size.sd > 0) {
575 total += sync_size + (am_size + 1);
576 data_position[i] = total;
577 total += data_size.sd + 2;
579 data_position[i] = total; // FIXME
582 t += data_size.sd + 0x10;
587 bool DISK::make_track(int trk, int side)
589 int track_size = get_track_size();
591 if(!get_track(trk, side)) {
592 // create a dummy track
593 for(int i = 0; i < track_size; i++) {
600 int sync_size = drive_mfm ? 12 : 6;
601 int am_size = drive_mfm ? 3 : 0;
602 int gap2_size = drive_mfm ? 22 : 11;
603 uint8 gap_data = drive_mfm ? 0x4e : 0xff;
606 memset(track, gap_data, track_size);
607 int q = sync_position[array_length(sync_position) - 1];
610 for(int i = 0; i < sync_size; i++) {
614 for(int i = 0; i < am_size; i++) {
622 for(int i = 0; i < sector_num.sd; i++) {
624 data_size.read_2bytes_le_from(t + 14);
625 int p = sync_position[i];
628 for(int j = 0; j < sync_size; j++) {
629 if(p < track_size) track[p++] = 0x00;
632 for(int j = 0; j < am_size; j++) {
633 if(p < track_size) track[p++] = 0xa1;
635 if(p < track_size) track[p++] = 0xfe;
637 if(p < track_size) track[p++] = t[0];
638 if(p < track_size) track[p++] = t[1];
639 if(p < track_size) track[p++] = t[2];
640 if(p < track_size) track[p++] = t[3];
642 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
643 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
644 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
645 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
646 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
647 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
649 for(int j = 0; j < gap2_size; j++) {
650 if(p < track_size) track[p++] = gap_data;
653 if(data_size.sd > 0) {
655 for(int j = 0; j < sync_size; j++) {
656 if(p < track_size) track[p++] = 0x00;
659 for(int j = 0; j < am_size; j++) {
660 if(p < track_size) track[p++] = 0xa1;
662 if(p < track_size) track[p++] = (t[7] != 0) ? 0xf8 : 0xfb;
665 for(int j = 0; j < data_size.sd; j++) {
666 if(p < track_size) track[p++] = t[0x10 + j];
667 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0x10 + j]]);
669 if(p < track_size) track[p++] = (crc >> 8) & 0xff;
670 if(p < track_size) track[p++] = (crc >> 0) & 0xff;
672 t += data_size.sd + 0x10;
677 bool DISK::get_sector(int trk, int side, int index)
679 sector_size.sd = sector_num.sd = 0;
682 // disk not inserted or invalid media type
683 if(!(inserted && check_media_type())) {
688 if(trk == -1 && side == -1) {
692 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
693 if(!(0 <= trkside && trkside < 164)) {
697 offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
699 if(!IS_VALID_TRACK(offset.d)) {
704 uint8* t = buffer + offset.d;
705 sector_num.read_2bytes_le_from(t + 4);
707 if(index >= sector_num.sd) {
712 for(int i = 0; i < index; i++) {
714 data_size.read_2bytes_le_from(t + 14);
715 t += data_size.sd + 0x10;
721 void DISK::set_sector_info(uint8 *t)
729 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[0]]);
730 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[1]]);
731 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[2]]);
732 crc = (uint16)((crc << 8) ^ crc_table[(uint8)(crc >> 8) ^ t[3]]);
733 id[4] = (crc >> 8) & 0xff;
734 id[5] = (crc >> 0) & 0xff;
735 // http://www,gnu-darwin.or.jp/www001/src/ports/emulators/quasi88/work/quasi88-0.6.3/document/FORMAT.TXT
736 // t[6]: 0x00 = double-density, 0x40 = single-density
737 // t[7]: 0x00 = normal, 0x10 = deleted mark
738 // t[8]: 0x00 = valid, 0x10 = valid (deleted data), 0xa0 = id crc error, 0xb0 = data crc error, 0xe0 = address mark missing, 0xf0 = data mark missing
740 deleted = (t[7] != 0);
742 // if(ignore_crc()) {
743 // crc_error = false;
745 // crc_error = (((t[8] & 0xf0) != 0x00) && ((t[8] & 0xf0) != 0x10));
746 addr_crc_error = ((t[8] & 0xf0) == 0xa0);
747 data_crc_error = ((t[8] & 0xf0) == 0xb0);
750 sector_size.read_2bytes_le_from(t + 14);
753 void DISK::set_deleted(bool value)
756 uint8 *t = sector - 0x10;
757 t[7] = value ? 0x10 : 0;
758 if((t[8] & 0xf0) == 0x00 || (t[8] & 0xf0) == 0x10) {
759 t[8] = (t[8] & 0x0f) | t[7];
765 void DISK::set_data_crc_error(bool value)
768 uint8 *t = sector - 0x10;
769 t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]);
771 data_crc_error = value;
774 void DISK::set_data_mark_missing()
777 uint8 *t = sector - 0x10;
778 //t[8] = (t[8] & 0x0f) | (value ? 0xb0 : t[7]); // FIXME: always data crc error ?
779 t[8] = (t[8] & 0x0f) | 0xf0;
783 //addr_crc_error = value;
784 data_crc_error = false;
787 bool DISK::format_track(int trk, int side)
789 // disk not inserted or invalid media type
790 if(!(inserted && check_media_type())) {
795 int trkside = is_1dd_image ? trk : (trk * 2 + (side & 1));
796 if(!(0 <= trkside && trkside < 164)) {
800 // create new empty track
803 trim_required = false;
805 memset(buffer + DISK_BUFFER_SIZE, 0, sizeof(buffer) - DISK_BUFFER_SIZE);
807 offset.d = DISK_BUFFER_SIZE;
808 offset.write_4bytes_le_to(buffer + 0x20 + trkside * 4);
810 trim_required = true;
815 void DISK::insert_sector(uint8 c, uint8 h, uint8 r, uint8 n, bool deleted, bool data_crc_error, uint8 fill_data, int length)
817 uint8* t = buffer + DISK_BUFFER_SIZE;
820 for(int i = 0; i < (sector_num.sd - 1); i++) {
821 t[4] = sector_num.b.l;
822 t[5] = sector_num.b.h;
824 data_size.read_2bytes_le_from(t + 14);
825 t += data_size.sd + 0x10;
831 t[4] = sector_num.b.l;
832 t[5] = sector_num.b.h;
833 t[6] = drive_mfm ? 0 : 0x40;
834 t[7] = deleted ? 0x10 : 0;
835 t[8] = data_crc_error ? 0xb0 : t[7];
836 t[14] = (length >> 0) & 0xff;
837 t[15] = (length >> 8) & 0xff;
838 memset(t + 16, fill_data, length);
843 void DISK::sync_buffer()
847 trim_required = false;
851 void DISK::trim_buffer()
853 int max_tracks = 164;
854 uint32 dest_offset = 0x2b0;
857 memset(tmp_buffer, 0, sizeof(tmp_buffer));
858 memcpy(tmp_buffer, buffer, 0x20);
861 for(int trkside = 0; trkside < 164; trkside++) {
863 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
864 if(src_trk_offset.d != 0) {
866 if(src_trk_offset.d < 0x2b0) {
867 max_tracks = (src_trk_offset.d - 0x20) >> 2;
870 if(src_trk_offset.d != 0x2b0) {
871 max_tracks = (src_trk_offset.d - 0x20) >> 2;
872 if(max_tracks > 164) {
873 dest_offset = 0x20 + max_tracks * 4);
882 for(int trkside = 0; trkside < max_tracks; trkside++) {
884 src_trk_offset.read_4bytes_le_from(buffer + 0x20 + trkside * 4);
886 pair dest_trk_offset;
887 dest_trk_offset.d = 0;
889 if(IS_VALID_TRACK(src_trk_offset.d)) {
890 uint8* t = buffer + src_trk_offset.d;
891 pair sector_num, data_size;
892 sector_num.read_2bytes_le_from(t + 4);
893 if(sector_num.sd != 0) {
894 dest_trk_offset.d = dest_offset;
895 for(int i = 0; i < sector_num.sd; i++) {
896 data_size.read_2bytes_le_from(t + 14);
897 memcpy(tmp_buffer + dest_offset, t, data_size.sd + 0x10);
898 dest_offset += data_size.sd + 0x10;
899 t += data_size.sd + 0x10;
903 dest_trk_offset.write_4bytes_le_to(tmp_buffer + 0x20 + trkside * 4);
907 file_size.d = dest_offset;
908 file_size.write_4bytes_le_to(tmp_buffer + 0x1c);
910 memset(buffer, 0, sizeof(buffer));
911 memcpy(buffer, tmp_buffer, (file_size.d > sizeof(buffer)) ? sizeof(buffer) : file_size.d);
918 } else if(inserted) {
919 return (media_type == MEDIA_TYPE_2HD) ? 360 : 300;
921 return (drive_type == DRIVE_TYPE_2HD) ? 360 : 300;
925 int DISK::get_track_size()
928 if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
929 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3100;
931 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
933 if(is_special_disk == SPECIAL_DISK_FM7_DEATHFORCE) {
934 return media_type == MEDIA_TYPE_144 ? 12500 : media_type == MEDIA_TYPE_2HD ? 10410 : drive_mfm ? 6300 : 3100;
936 return drive_type == DRIVE_TYPE_144 ? 12500 : drive_type == DRIVE_TYPE_2HD ? 10410 : drive_mfm ? 6250 : 3100;
940 double DISK::get_usec_per_track()
942 return 1000000.0 / (get_rpm() / 60.0);
945 double DISK::get_usec_per_bytes(int bytes)
947 return 1000000.0 / (get_track_size() * (get_rpm() / 60.0)) * bytes;
950 int DISK::get_bytes_per_usec(double usec)
952 return (int)(usec / get_usec_per_bytes(1) + 0.5);
955 bool DISK::check_media_type()
959 return (media_type == MEDIA_TYPE_2D);
961 return (media_type == MEDIA_TYPE_2D || media_type == MEDIA_TYPE_2DD);
963 return (media_type == MEDIA_TYPE_2HD);
965 return (media_type == MEDIA_TYPE_144);
967 return true; // always okay
974 #define COPYBUFFER(src, size) { \
975 if(file_size.d + (size) > DISK_BUFFER_SIZE) { \
978 memcpy(buffer + file_size.d, (src), (size)); \
979 file_size.d += (size); \
994 uint8 dens, del, stat;
999 // teledisk image decoder
1002 this teledisk image decoder is based on:
1004 LZHUF.C English version 1.0 based on Japanese version 29-NOV-1988
1005 LZSS coded by Haruhiko OKUMURA
1006 Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
1007 Edited and translated to English by Kenji RIKITAKE
1031 uint8 nsec, trk, head;
1040 bool DISK::teledisk_to_d88()
1050 // check teledisk header
1051 fi->Fseek(0, FILEIO_SEEK_SET);
1052 fi->Fread(&hdr, sizeof(td_hdr_t), 1);
1053 if(hdr.sig[0] == 't' && hdr.sig[1] == 'd') {
1054 // decompress to the temporary file
1055 FILEIO* fo = new FILEIO();
1056 if(!fo->Fopen(temp_path, FILEIO_WRITE_BINARY)) {
1063 if((rd = decode(obuf, 512)) > 0) {
1064 fo->Fwrite(obuf, rd, 1);
1072 // reopen the temporary file
1074 if(!fi->Fopen(temp_path, FILEIO_READ_BINARY)) {
1078 if(hdr.flag & 0x80) {
1080 fi->Fread(&cmt, sizeof(td_cmt_t), 1);
1081 fi->Fseek(cmt.len, FILEIO_SEEK_CUR);
1087 // create d88 header
1088 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1089 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "TELEDISK");
1090 d88_hdr.protect = 0; // non-protected
1091 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1094 int trkcnt = 0, trkptr = sizeof(d88_hdr_t);
1095 fi->Fread(&trk, sizeof(td_trk_t), 1);
1096 while(trk.nsec != 0xff) {
1097 d88_hdr.trkptr[trkcnt++] = trkptr;
1098 if(hdr.sides == 1) {
1102 // read sectors in this track
1103 for(int i = 0; i < trk.nsec; i++) {
1104 uint8 buf[2048], dst[2048];
1105 memset(buf, 0, sizeof(buf));
1106 memset(dst, 0, sizeof(dst));
1108 // read sector header
1109 fi->Fread(&sct, sizeof(td_sct_t), 1);
1111 // create d88 sector header
1112 memset(&d88_sct, 0, sizeof(d88_sct_t));
1117 d88_sct.nsec = trk.nsec;
1118 d88_sct.dens = (hdr.dens & 0x80) ? 0x40 : 0;
1119 d88_sct.del = (sct.ctrl & 4) ? 0x10 : 0;
1120 d88_sct.stat = (sct.ctrl & 2) ? 0xb0 : d88_sct.del;
1121 d88_sct.size = secsize[sct.n & 3];
1123 // create sector image
1124 if(sct.ctrl & 0x30) {
1125 d88_sct.stat = 0xf0; // data mark missing
1128 // read sector source
1129 int len = fi->Fgetc();
1130 len += fi->Fgetc() * 256 - 1;
1131 int flag = fi->Fgetc(), d = 0;
1132 fi->Fread(buf, len, 1);
1136 memcpy(dst, buf, len);
1137 } else if(flag == 1) {
1139 len2.read_2bytes_le_from(buf);
1144 } else if(flag == 2) {
1145 for(int s = 0; s < len;) {
1146 int type = buf[s++];
1147 int len2 = buf[s++];
1150 dst[d++] = buf[s++];
1152 } else if(type < 5) {
1158 for(int j = 0; j < n; j++) {
1162 for(int j = 0; j < n; j++) {
1167 break; // unknown type
1171 break; // unknown flag
1176 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1177 COPYBUFFER(dst, d88_sct.size);
1178 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1181 fi->Fread(&trk, sizeof(td_trk_t), 1);
1183 d88_hdr.type = ((hdr.dens & 3) == 2) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 45) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1184 d88_hdr.size = trkptr;
1185 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1189 int DISK::next_word()
1191 if(ibufndx >= ibufcnt) {
1192 ibufndx = ibufcnt = 0;
1193 memset(inbuf, 0, 512);
1194 for(int i = 0; i < 512; i++) {
1195 int d = fi->Fgetc();
1206 while(getlen <= 8) {
1207 getbuf |= inbuf[ibufndx++] << (8 - getlen);
1215 if(next_word() < 0) {
1221 return (i < 0) ? 1 : 0;
1224 int DISK::get_byte()
1226 if(next_word() != 0) {
1236 void DISK::start_huff()
1239 for(i = 0; i < N_CHAR; i++) {
1241 son[i] = i + TABLE_SIZE;
1242 prnt[i + TABLE_SIZE] = i;
1245 while(j <= ROOT_POSITION) {
1246 freq[j] = freq[i] + freq[i + 1];
1248 prnt[i] = prnt[i + 1] = j;
1251 freq[TABLE_SIZE] = 0xffff;
1252 prnt[ROOT_POSITION] = 0;
1255 void DISK::reconst()
1259 for(i = 0; i < TABLE_SIZE; i++) {
1260 if(son[i] >= TABLE_SIZE) {
1261 freq[j] = (freq[i] + 1) / 2;
1266 for(i = 0, j = N_CHAR; j < TABLE_SIZE; i += 2, j++) {
1268 f = freq[j] = freq[i] + freq[k];
1269 for(k = j - 1; f < freq[k]; k--);
1272 memmove(&freq[k + 1], &freq[k], l);
1274 memmove(&son[k + 1], &son[k], l);
1277 for(i = 0; i < TABLE_SIZE; i++) {
1278 if((k = son[i]) >= TABLE_SIZE) {
1281 prnt[k] = prnt[k + 1] = i;
1286 void DISK::update(int c)
1289 if(freq[ROOT_POSITION] == MAX_FREQ) {
1292 c = prnt[c + TABLE_SIZE];
1295 if(k > freq[l = c + 1]) {
1296 while(k > freq[++l]);
1302 if(i < TABLE_SIZE) {
1308 if(j < TABLE_SIZE) {
1315 while((c = prnt[c]) != 0);
1318 short DISK::decode_char()
1321 uint16 c = son[ROOT_POSITION];
1322 while(c < TABLE_SIZE) {
1323 if((ret = get_bit()) < 0) {
1334 short DISK::decode_position()
1338 if((bit = get_byte()) < 0) {
1342 c = (uint16)d_code[i] << 6;
1345 if((bit = get_bit()) < 0) {
1350 return (c | i & 0x3f);
1353 void DISK::init_decode()
1355 ibufcnt= ibufndx = bufcnt = getbuf = 0;
1358 for(int i = 0; i < STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE; i++) {
1361 ptr = STRING_BUFFER_SIZE - LOOKAHEAD_BUFFER_SIZE;
1364 int DISK::decode(uint8 *buf, int len)
1368 for(count = 0; count < len;) {
1370 if((c = decode_char()) < 0) {
1374 *(buf++) = (uint8)c;
1375 text_buf[ptr++] = (uint8)c;
1376 ptr &= (STRING_BUFFER_SIZE - 1);
1379 if((pos = decode_position()) < 0) {
1382 bufpos = (ptr - pos - 1) & (STRING_BUFFER_SIZE - 1);
1383 bufcnt = c - 255 + THRESHOLD;
1387 while(bufndx < bufcnt && count < len) {
1388 c = text_buf[(bufpos + bufndx) & (STRING_BUFFER_SIZE - 1)];
1389 *(buf++) = (uint8)c;
1391 text_buf[ptr++] = (uint8)c;
1392 ptr &= (STRING_BUFFER_SIZE - 1);
1395 if(bufndx >= bufcnt) {
1396 bufndx = bufcnt = 0;
1403 // imagedisk image decoder
1413 bool DISK::imagedisk_to_d88()
1420 fi->Fseek(0, FILEIO_SEEK_SET);
1422 while((tmp = fi->Fgetc()) != 0x1a) {
1431 // create d88 header
1432 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1433 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "IMAGEDISK");
1434 d88_hdr.protect = 0; // non-protected
1435 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1438 int trkptr = sizeof(d88_hdr_t);
1439 int trkcnt = 0, mode;
1441 for(int t = 0; t < 164; t++) {
1442 // check end of file
1443 if(fi->Fread(&trk, sizeof(imd_trk_t), 1) != 1) {
1448 // check track header
1450 mode = trk.mode % 3; // 0=500kbps, 1=300kbps, 2=250kbps
1455 d88_hdr.trkptr[t] = trkptr;
1458 uint8 c[64], h[64], r[64];
1459 fi->Fread(r, trk.nsec, 1);
1460 if(trk.head & 0x80) {
1461 fi->Fread(c, trk.nsec, 1);
1463 memset(c, trk.cyl, sizeof(c));
1465 if(trk.head & 0x40) {
1466 fi->Fread(h, trk.nsec, 1);
1468 memset(h, trk.head & 1, sizeof(h));
1471 // read sectors in this track
1472 for(int i = 0; i < trk.nsec; i++) {
1473 // create d88 sector header
1474 int sectype = fi->Fgetc();
1478 memset(&d88_sct, 0, sizeof(d88_sct_t));
1482 d88_sct.n = trk.size;
1483 d88_sct.nsec = trk.nsec;
1484 d88_sct.dens = (trk.mode < 3) ? 0x40 : 0;
1485 d88_sct.del = (sectype == 3 || sectype == 4 || sectype == 7 || sectype == 8) ? 0x10 : 0;
1486 d88_sct.stat = (sectype == 5 || sectype == 6 || sectype == 7 || sectype == 8) ? 0xb0 : d88_sct.del;
1487 d88_sct.size = secsize[trk.size & 7];
1489 // create sector image
1491 if(sectype == 1 || sectype == 3 || sectype == 5 || sectype == 7) {
1493 fi->Fread(dst, d88_sct.size, 1);
1494 } else if(sectype == 2 || sectype == 4 || sectype == 6 || sectype == 8) {
1496 int tmp = fi->Fgetc();
1497 memset(dst, tmp, d88_sct.size);
1499 d88_sct.stat = 0xf0; // data mark missing
1504 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1505 COPYBUFFER(dst, d88_sct.size);
1506 trkptr += sizeof(d88_sct_t) + d88_sct.size;
1509 d88_hdr.type = (mode == 0) ? MEDIA_TYPE_2HD : ((trkcnt >> 1) > 60) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2D;
1510 d88_hdr.size = trkptr;
1511 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1515 // cpdread image decoder (from MESS formats/dsk_dsk.c)
1517 bool DISK::cpdread_to_d88(int extended)
1523 // get cylinder number and side number
1524 memcpy(tmp_buffer, buffer, file_size.d);
1525 int ncyl = tmp_buffer[0x30];
1526 int nside = tmp_buffer[0x31];
1531 // create d88 header
1532 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1533 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "CPDRead");
1534 d88_hdr.protect = 0; // non-protected
1535 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1538 int trkofs = 0x100, trkofs_ptr = 0x34;
1539 int trkptr = sizeof(d88_hdr_t);
1541 for(int c = 0; c < ncyl; c++) {
1542 for(int h = 0; h < nside; h++) {
1543 // read sectors in this track
1544 uint8 *track_info = tmp_buffer + trkofs;
1545 int cyl = track_info[0x10];
1546 int side = track_info[0x11] & 1;
1547 int nsec = track_info[0x15];
1548 int size = 1 << (track_info[0x14] + 7); // standard
1549 int sctofs = trkofs + 0x100;
1554 d88_hdr.trkptr[2 * cyl + side] = trkptr;
1556 for(int s = 0; s < nsec; s++) {
1558 uint8 *sector_info = tmp_buffer + trkofs + 0x18 + s * 8;
1560 size = sector_info[6] + sector_info[7] * 256;
1563 // create d88 sector header
1564 memset(&d88_sct, 0, sizeof(d88_sct_t));
1565 d88_sct.c = sector_info[0];
1566 d88_sct.h = sector_info[1];
1567 d88_sct.r = sector_info[2];
1568 d88_sct.n = sector_info[3];
1569 d88_sct.nsec = nsec;
1571 d88_sct.del = (sector_info[5] == 0xb2) ? 0x10 : 0;
1572 d88_sct.stat = (size == 0) ? 0xf0 : (sector_info[5] == 0xb5) ? 0xb0 : d88_sct.del;
1573 d88_sct.size = size;
1576 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1577 COPYBUFFER(tmp_buffer + sctofs, size);
1578 trkptr += sizeof(d88_sct_t) + size;
1584 trkofs += tmp_buffer[trkofs_ptr++] * 256;
1586 trkofs += tmp_buffer[0x32] + tmp_buffer[0x33] * 256;
1590 d88_hdr.type = (total < (368640 + 655360) / 2) ? MEDIA_TYPE_2D : (total < (737280 + 1228800) / 2) ? MEDIA_TYPE_2DD : MEDIA_TYPE_2HD;
1591 d88_hdr.size = trkptr;
1592 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1596 // solid image decoder
1598 bool DISK::solid_to_d88(int type, int ncyl, int nside, int nsec, int size)
1606 // create d88 header
1607 memset(&d88_hdr, 0, sizeof(d88_hdr_t));
1608 _strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "STANDARD");
1609 d88_hdr.protect = 0; // non-protected
1610 d88_hdr.type = (type == MEDIA_TYPE_144) ? MEDIA_TYPE_2HD : type;
1612 COPYBUFFER(&d88_hdr, sizeof(d88_hdr_t));
1615 for(int i = 0; i < 8; i++) {
1616 if(size == (128 << i)) {
1623 int trkptr = sizeof(d88_hdr_t);
1624 for(int c = 0; c < ncyl; c++) {
1625 for(int h = 0; h < nside; h++) {
1626 d88_hdr.trkptr[t++] = trkptr;
1631 // read sectors in this track
1632 for(int s = 0; s < nsec; s++) {
1633 // create d88 sector header
1634 memset(&d88_sct, 0, sizeof(d88_sct_t));
1639 d88_sct.nsec = nsec;
1643 d88_sct.size = size;
1645 // create sector image
1647 memset(dst, 0xe5, sizeof(dst));
1648 fi->Fread(dst, size, 1);
1651 COPYBUFFER(&d88_sct, sizeof(d88_sct_t));
1652 COPYBUFFER(dst, size);
1653 trkptr += sizeof(d88_sct_t) + size;
1657 d88_hdr.size = trkptr;
1658 memcpy(buffer, &d88_hdr, sizeof(d88_hdr_t));
1662 #define STATE_VERSION 6
1664 void DISK::save_state(FILEIO* state_fio)
1666 state_fio->FputUint32(STATE_VERSION);
1668 state_fio->Fwrite(buffer, sizeof(buffer), 1);
1669 state_fio->Fwrite(orig_path, sizeof(orig_path), 1);
1670 state_fio->Fwrite(dest_path, sizeof(dest_path), 1);
1671 state_fio->FputUint32(file_size.d);
1672 state_fio->FputInt32(file_bank);
1673 state_fio->FputUint32(crc32);
1674 state_fio->Fwrite(fdi_header, sizeof(fdi_header), 1);
1675 state_fio->FputBool(inserted);
1676 state_fio->FputBool(ejected);
1677 state_fio->FputBool(write_protected);
1678 state_fio->FputBool(changed);
1679 state_fio->FputUint8(media_type);
1680 state_fio->FputBool(is_solid_image);
1681 state_fio->FputBool(is_fdi_image);
1682 state_fio->FputBool(is_1dd_image);
1683 state_fio->FputInt32(is_special_disk);
1684 state_fio->Fwrite(track, sizeof(track), 1);
1685 state_fio->FputInt32(sector_num.sd);
1686 state_fio->FputBool(invalid_format);
1687 state_fio->FputBool(no_skew);
1688 state_fio->Fwrite(sync_position, sizeof(sync_position), 1);
1689 state_fio->Fwrite(id_position, sizeof(id_position), 1);
1690 state_fio->Fwrite(data_position, sizeof(data_position), 1);
1691 state_fio->FputInt32(sector ? (int)(sector - buffer) : -1);
1692 state_fio->FputInt32(sector_size.sd);
1693 state_fio->Fwrite(id, sizeof(id), 1);
1694 state_fio->FputUint8(density);
1695 state_fio->FputBool(deleted);
1696 state_fio->FputBool(addr_crc_error);
1697 state_fio->FputBool(data_crc_error);
1698 state_fio->FputUint8(drive_type);
1699 state_fio->FputInt32(drive_rpm);
1700 state_fio->FputBool(drive_mfm);
1703 bool DISK::load_state(FILEIO* state_fio)
1705 if(state_fio->FgetUint32() != STATE_VERSION) {
1708 state_fio->Fread(buffer, sizeof(buffer), 1);
1709 state_fio->Fread(orig_path, sizeof(orig_path), 1);
1710 state_fio->Fread(dest_path, sizeof(dest_path), 1);
1711 file_size.d = state_fio->FgetUint32();
1712 file_bank = state_fio->FgetInt32();
1713 crc32 = state_fio->FgetUint32();
1714 state_fio->Fread(fdi_header, sizeof(fdi_header), 1);
1715 inserted = state_fio->FgetBool();
1716 ejected = state_fio->FgetBool();
1717 write_protected = state_fio->FgetBool();
1718 changed = state_fio->FgetBool();
1719 media_type = state_fio->FgetUint8();
1720 is_solid_image = state_fio->FgetBool();
1721 is_fdi_image = state_fio->FgetBool();
1722 is_1dd_image = state_fio->FgetBool();
1723 is_special_disk = state_fio->FgetInt32();
1724 state_fio->Fread(track, sizeof(track), 1);
1725 sector_num.sd = state_fio->FgetInt32();
1726 invalid_format = state_fio->FgetBool();
1727 no_skew = state_fio->FgetBool();
1728 state_fio->Fread(sync_position, sizeof(sync_position), 1);
1729 state_fio->Fread(id_position, sizeof(id_position), 1);
1730 state_fio->Fread(data_position, sizeof(data_position), 1);
1731 int offset = state_fio->FgetInt32();
1732 sector = (offset != -1) ? buffer + offset : NULL;
1733 sector_size.sd = state_fio->FgetInt32();
1734 state_fio->Fread(id, sizeof(id), 1);
1735 density = state_fio->FgetUint8();
1736 deleted = state_fio->FgetBool();
1737 addr_crc_error = state_fio->FgetBool();
1738 data_crc_error = state_fio->FgetBool();
1739 drive_type = state_fio->FgetUint8();
1740 drive_rpm = state_fio->FgetInt32();
1741 drive_mfm = state_fio->FgetBool();