OSDN Git Service

[VM][General] Merge Upstream 20180530.
[csp-qt/common_source_project-fm7.git] / source / src / vm / upd765a.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : M88
5         Author : Takeda.Toshiya
6         Date   : 2006.09.17-
7
8         [ uPD765A ]
9 */
10
11 #include "upd765a.h"
12 #include "disk.h"
13 #include "noise.h"
14
15 #define EVENT_PHASE     0
16 #define EVENT_DRQ       1
17 #define EVENT_LOST      2
18 #define EVENT_RESULT7   3
19 #define EVENT_INDEX     4
20 #define EVENT_SEEK_STEP 5       // 5-8
21 #define EVENT_SEEK_END  9       // 9-12
22 #define EVENT_UNLOAD    13      // 13-16
23
24 #define PHASE_IDLE      0
25 #define PHASE_CMD       1
26 #define PHASE_EXEC      2
27 #define PHASE_READ      3
28 #define PHASE_WRITE     4
29 #define PHASE_SCAN      5
30 #define PHASE_TC        6
31 #define PHASE_TIMER     7
32 #define PHASE_RESULT    8
33
34 #define S_D0B   0x01
35 #define S_D1B   0x02
36 #define S_D2B   0x04
37 #define S_D3B   0x08
38 #define S_CB    0x10
39 #define S_NDM   0x20
40 #define S_DIO   0x40
41 #define S_RQM   0x80
42
43 #define ST0_NR  0x000008
44 #define ST0_EC  0x000010
45 #define ST0_SE  0x000020
46 #define ST0_AT  0x000040
47 #define ST0_IC  0x000080
48 #define ST0_AI  0x0000c0
49
50 #define ST1_MA  0x000100
51 #define ST1_NW  0x000200
52 #define ST1_ND  0x000400
53 #define ST1_OR  0x001000
54 #define ST1_DE  0x002000
55 #define ST1_EN  0x008000
56
57 #define ST2_MD  0x010000
58 #define ST2_BC  0x020000
59 #define ST2_SN  0x040000
60 #define ST2_SH  0x080000
61 #define ST2_NC  0x100000
62 #define ST2_DD  0x200000
63 #define ST2_CM  0x400000
64
65 #define ST3_HD  0x04
66 #define ST3_TS  0x08
67 #define ST3_T0  0x10
68 #define ST3_RY  0x20
69 #define ST3_WP  0x40
70 #define ST3_FT  0x80
71
72 #define DRIVE_MASK      3
73
74 #define REGISTER_PHASE_EVENT(phs, usec) { \
75         if(phase_id != -1) { \
76                 cancel_event(this, phase_id); \
77         } \
78         event_phase = phs; \
79         register_event(this, EVENT_PHASE, 100, false, &phase_id); \
80 }
81
82 #define REGISTER_PHASE_EVENT_NEW(phs, usec) { \
83         if(phase_id != -1) { \
84                 cancel_event(this, phase_id); \
85         } \
86         event_phase = phs; \
87         register_event(this, EVENT_PHASE, usec, false, &phase_id); \
88 }
89
90 #define REGISTER_DRQ_EVENT() { \
91         double usec = disk[hdu & DRIVE_MASK]->get_usec_per_bytes(1) - get_passed_usec(prev_drq_clock); \
92         if(usec < 4) { \
93                 usec = 4; \
94         } \
95         register_event(this, EVENT_DRQ, usec, false, &drq_id); \
96 }
97
98 #define CANCEL_EVENT() { \
99         if(phase_id != -1) { \
100                 cancel_event(this, phase_id); \
101                 phase_id = -1; \
102         } \
103         if(drq_id != -1) { \
104                 cancel_event(this, drq_id); \
105                 drq_id = -1; \
106         } \
107         if(lost_id != -1) { \
108                 cancel_event(this, lost_id); \
109                 lost_id = -1; \
110         } \
111         if(result7_id != -1) { \
112                 cancel_event(this, result7_id); \
113                 result7_id = -1; \
114         } \
115         for(int d = 0; d < 4; d++) { \
116                 if(seek_step_id[d] != -1) { \
117                         cancel_event(this, seek_step_id[d]); \
118                         seek_step_id[d] = -1; \
119                 } \
120                 if(seek_end_id[d] != -1) { \
121                         cancel_event(this, seek_end_id[d]); \
122                         seek_end_id[d] = -1; \
123                 } \
124                 if(head_unload_id[d] != -1) { \
125                         cancel_event(this, head_unload_id[d]); \
126                         head_unload_id[d] = -1; \
127                 } \
128         } \
129 }
130
131 void UPD765A::initialize()
132 {
133         DEVICE::initialize();
134         if(osd->check_feature(_T("MAX_DRIVE"))) {
135                 _max_drive = osd->get_feature_int_value(_T("MAX_DRIVE"));
136                 if((_max_drive < 0) || (_max_drive > 4)) _max_drive = 4;
137         } else {
138                 _max_drive = 0;
139         }
140         //_fdc_debug_log = osd->check_feature(_T("_FDC_DEBUG_LOG"));
141         _fdc_debug_log = config.special_debug_fdc;
142         
143         _upd765a_dma_mode = osd->check_feature(_T("UPD765A_DMA_MODE"));
144         _upd765a_ext_drvsel = osd->check_feature(_T("UPD765A_EXT_DRVSEL"));
145         _upd765a_sence_intstat_result = osd->check_feature(_T("UPD765A_SENCE_INTSTAT_RESULT"));
146         _upd765a_dont_wait_seek = osd->check_feature(_T("UPD765A_DONT_WAIT_SEEK"));
147         _upd765a_no_st0_at_for_seek = osd->check_feature(_T("UPD765A_NO_ST0_AT_FOR_SEEK"));
148         _upd765a_wait_result7 = osd->check_feature(_T("UPD765A_WAIT_RESULT7"));
149         _upd765a_no_st1_en_or_for_result7 = osd->check_feature(_T("UPD765A_NO_ST1_EN_OR_FOR_RESULT7"));
150         
151         // initialize d88 handler
152         for(int i = 0; i < 4; i++) {
153                 disk[i] = new DISK(emu);
154                 disk[i]->set_device_name(_T("%s/Disk #%d"), this_device_name, i + 1);
155         }
156         
157         // initialize noise
158         if(d_noise_seek != NULL) {
159                 d_noise_seek->set_device_name(_T("Noise Player (FDD Seek)"));
160                 if(!d_noise_seek->load_wav_file(_T("FDDSEEK.WAV"))) {
161                         if(!d_noise_seek->load_wav_file(_T("FDDSEEK1.WAV"))) {
162                                 d_noise_seek->load_wav_file(_T("SEEK.WAV"));
163                         }
164                 }
165                 d_noise_seek->set_mute(!config.sound_noise_fdd);
166         }
167         if(d_noise_head_down != NULL) {
168                 d_noise_head_down->set_device_name(_T("Noise Player (FDD Head Load)"));
169                 d_noise_head_down->load_wav_file(_T("HEADDOWN.WAV"));
170                 d_noise_head_down->set_mute(!config.sound_noise_fdd);
171         }
172         if(d_noise_head_up != NULL) {
173                 d_noise_head_up->set_device_name(_T("Noise Player (FDD Head Unload)"));
174                 d_noise_head_up->load_wav_file(_T("HEADUP.WAV"));
175                 d_noise_head_up->set_mute(!config.sound_noise_fdd);
176         }
177         
178         // initialize fdc
179         memset(fdc, 0, sizeof(fdc));
180         memset(buffer, 0, sizeof(buffer));
181         
182         phase = prevphase = PHASE_IDLE;
183         status = S_RQM;
184         seekstat = 0;
185         bufptr = buffer; // temporary
186         phase_id = drq_id = lost_id = result7_id = -1;
187         for(int i = 0; i < 4; i++) {
188                 seek_step_id[i] = seek_end_id[i] = head_unload_id[i] = -1;
189         }
190         step_rate_time = head_unload_time = 0;
191         no_dma_mode = false;
192         motor_on = false;       // motor off
193         reset_signal = true;
194         irq_masked = drq_masked = false;
195 //#ifdef UPD765A_DMA_MODE
196         dma_data_lost = false;
197 //#endif
198         
199         set_irq(false);
200         set_drq(false);
201 //#ifdef UPD765A_EXT_DRVSEL
202         if(_upd765a_ext_drvsel) {
203                 hdu = 0;
204         } else {
205 //#else
206                 set_hdu(0);
207         }
208 //#endif
209         
210         // index hole event
211         if(outputs_index.count) {
212                 register_event(this, EVENT_INDEX, 4, true, NULL);
213                 prev_index = false;
214         }
215 }
216
217 void UPD765A::release()
218 {
219         for(int i = 0; i < 4; i++) {
220                 if(disk[i]) {
221                         disk[i]->close();
222                         delete disk[i];
223                 }
224         }
225 }
226
227 void UPD765A::reset()
228 {
229         shift_to_idle();
230 //      CANCEL_EVENT();
231         phase_id = drq_id = lost_id = result7_id = -1;
232         for(int i = 0; i < 4; i++) {
233                 if(seek_step_id[i] != -1) {
234                         // loop events are not canceled automatically in EVENT::reset()
235                         cancel_event(this, seek_step_id[i]);
236                 }
237                 seek_step_id[i] = seek_end_id[i] = head_unload_id[i] = -1;
238         }
239         set_irq(false);
240         set_drq(false);
241 }
242
243 static const char* get_command_name(uint8_t data)
244 {
245         static char name[16];
246         
247         switch(data & 0x1f) {
248         case 0x02:
249                 my_sprintf_s(name, 16, _T("RD DIAGNOSTIC"));
250                 break;
251         case 0x03:
252                 my_sprintf_s(name, 16, _T("SPECIFY      "));
253                 break;
254         case 0x04:
255                 my_sprintf_s(name, 16, _T("SENCE DEVSTAT"));
256                 break;
257         case 0x05:
258         case 0x09:
259                 my_sprintf_s(name, 16, _T("WRITE DATA   "));
260                 break;
261         case 0x06:
262         case 0x0c:
263                 my_sprintf_s(name, 16, _T("READ DATA    "));
264                 break;
265         case 0x07:
266                 my_sprintf_s(name, 16, _T("RECALIB      "));
267                 break;
268         case 0x08:
269                 my_sprintf_s(name, 16, _T("SENCE INTSTAT"));
270                 break;
271         case 0x0a:
272                 my_sprintf_s(name, 16, _T("READ ID      "));
273                 break;
274         case 0x0d:
275                 my_sprintf_s(name, 16, _T("WRITE ID     "));
276                 break;
277         case 0x0f:
278                 my_sprintf_s(name, 16, _T("SEEK         "));
279                 break;
280         case 0x11:
281         case 0x19:
282         case 0x1d:
283                 my_sprintf_s(name, 16, _T("SCAN         "));
284                 break;
285         default:
286                 my_sprintf_s(name, 16, _T("INVALID      "));
287                 break;
288         }
289         return name;
290 }
291
292 void UPD765A::write_io8(uint32_t addr, uint32_t data)
293 {
294         if(addr & 1) {
295                 // fdc data
296                 if((status & (S_RQM | S_DIO)) == S_RQM) {
297                         status &= ~S_RQM;
298                         
299                         switch(phase) {
300                         case PHASE_IDLE:
301 //#ifdef _FDC_DEBUG_LOG
302                                 if(_fdc_debug_log) {
303                                         this->out_debug_log(_T("FDC: CMD=%2x %s\n"), data, get_command_name(data));
304                                 }
305 //#endif
306                                 command = data;
307                                 process_cmd(command & 0x1f);
308                                 break;
309                         case PHASE_CMD:
310 //#ifdef _FDC_DEBUG_LOG
311                                 if(_fdc_debug_log) this->force_out_debug_log(_T("FDC: PARAM=%2x\n"), data); // emu->force_out_debug_log()
312 //#endif
313                                 *bufptr++ = data;
314                                 if(--count) {
315                                         status |= S_RQM;
316                                 } else {
317                                         process_cmd(command & 0x1f);
318                                 }
319                                 break;
320                                 
321                         case PHASE_WRITE:
322 //#ifdef _FDC_DEBUG_LOG
323                                 if(_fdc_debug_log) this->force_out_debug_log(_T("FDC: WRITE=%2x\n"), data); // emu->force_out_debug_log()
324 //#endif
325                                 *bufptr++ = data;
326                                 set_drq(false);
327                                 if(--count) {
328                                         REGISTER_DRQ_EVENT();
329                                 } else {
330                                         process_cmd(command & 0x1f);
331                                 }
332                                 fdc[hdu & DRIVE_MASK].access = true;
333                                 break;
334                                 
335                         case PHASE_SCAN:
336                                 if(data != 0xff) {
337                                         if(((command & 0x1f) == 0x11 && *bufptr != data) ||
338                                            ((command & 0x1f) == 0x19 && *bufptr >  data) ||
339                                            ((command & 0x1f) == 0x1d && *bufptr <  data)) {
340                                                 result &= ~ST2_SH;
341                                         }
342                                 }
343                                 bufptr++;
344                                 set_drq(false);
345                                 if(--count) {
346                                         REGISTER_DRQ_EVENT();
347                                 } else {
348                                         cmd_scan();
349                                 }
350                                 fdc[hdu & DRIVE_MASK].access = true;
351                                 break;
352                         }
353                 }
354         }
355 }
356
357 uint32_t UPD765A::read_io8(uint32_t addr)
358 {
359         if(addr & 1) {
360                 // fdc data
361                 if((status & (S_RQM | S_DIO)) == (S_RQM | S_DIO)) {
362                         uint8_t data;
363                         status &= ~S_RQM;
364                         
365                         switch(phase) {
366                         case PHASE_RESULT:
367                                 data = *bufptr++;
368 //#ifdef _FDC_DEBUG_LOG
369                                 if(_fdc_debug_log) this->force_out_debug_log(_T("FDC: RESULT=%2x\n"), data); // emu->force_out_debug_log()
370 //#endif
371                                 if(--count) {
372                                         status |= S_RQM;
373                                 } else {
374                                         // EPSON QC-10 CP/M Plus
375                                         bool clear_irq = true;
376                                         if((command & 0x1f) == 0x08) {
377                                                 for(int i = 0; i < 4; i++) {
378                                                         if(fdc[i].result) {
379                                                                 clear_irq = false;
380                                                                 break;
381                                                         }
382                                                 }
383                                         }
384                                         if(clear_irq) {
385                                                 set_irq(false);
386                                         }
387                                         shift_to_idle();
388                                 }
389                                 return data;
390                                 
391                         case PHASE_READ:
392                                 data = *bufptr++;
393 //#ifdef _FDC_DEBUG_LOG
394                                 if(_fdc_debug_log) this->force_out_debug_log(_T("FDC: READ=%2x\n"), data);// emu->force_out_debug_log()
395 //#endif
396                                 set_drq(false);
397                                 if(--count) {
398                                         REGISTER_DRQ_EVENT();
399                                 } else {
400                                         process_cmd(command & 0x1f);
401                                 }
402                                 fdc[hdu & DRIVE_MASK].access = true;
403                                 return data;
404                         }
405                 }
406                 return 0xff;
407         } else {
408                 // FIXME: dirty patch for PC-8801 Kimochi Disk 2
409                 if(phase_id != -1 && event_phase == PHASE_EXEC) {
410                         cancel_event(this, phase_id);
411                         phase_id = -1;
412                         phase = event_phase;
413                         process_cmd(command & 0x1f);
414                 }
415                 // fdc status
416 //#ifdef _FDC_DEBUG_LOG
417 //              if(_fdc_debug_log) this->out_debug_log(_T("FDC: STATUS=%2x\n"), seekstat | status);
418 //#endif
419                 return seekstat | status;
420         }
421 }
422
423 void UPD765A::write_dma_io8(uint32_t addr, uint32_t data)
424 {
425 //#ifdef UPD765A_DMA_MODE
426         // EPSON QC-10 CP/M Plus
427         if(_upd765a_dma_mode) dma_data_lost = false;
428 //#endif
429         write_io8(1, data);
430 }
431
432 uint32_t UPD765A::read_dma_io8(uint32_t addr)
433 {
434 //#ifdef UPD765A_DMA_MODE
435         // EPSON QC-10 CP/M Plus
436         if(_upd765a_dma_mode) dma_data_lost = false;
437 //#endif
438         return read_io8(1);
439 }
440
441 void UPD765A::write_signal(int id, uint32_t data, uint32_t mask)
442 {
443         if(id == SIG_UPD765A_RESET) {
444                 bool next = ((data & mask) != 0);
445                 if(!reset_signal && next) {
446                         reset();
447                 }
448                 reset_signal = next;
449         } else if(id == SIG_UPD765A_TC) {
450                 if(phase == PHASE_EXEC || phase == PHASE_READ || phase == PHASE_WRITE || phase == PHASE_SCAN || (phase == PHASE_RESULT && count == 7)) {
451                         if(data & mask) {
452                                 prevphase = phase;
453                                 phase = PHASE_TC;
454                                 process_cmd(command & 0x1f);
455                         }
456                 }
457         } else if(id == SIG_UPD765A_MOTOR) {
458                 motor_on = ((data & mask) != 0);
459         } else if(id == SIG_UPD765A_MOTOR_NEG) {
460                 motor_on = ((data & mask) == 0);
461 //#ifdef UPD765A_EXT_DRVSEL
462         } else if(id == SIG_UPD765A_DRVSEL) {
463                 if(_upd765a_ext_drvsel) {
464                         hdu = (hdu & 4) | (data & DRIVE_MASK);
465                         write_signals(&outputs_hdu, hdu);
466                 }
467 //#endif
468         } else if(id == SIG_UPD765A_IRQ_MASK) {
469                 if(!(irq_masked = ((data & mask) != 0))) {
470                         write_signals(&outputs_irq, 0);
471                 }
472         } else if(id == SIG_UPD765A_DRQ_MASK) {
473                 if(!(drq_masked = ((data & mask) != 0))) {
474                         write_signals(&outputs_drq, 0);
475                 }
476         } else if(id == SIG_UPD765A_FREADY) {
477                 // for NEC PC-98x1 series
478                 force_ready = ((data & mask) != 0);
479         }
480 }
481
482 uint32_t UPD765A::read_signal(int ch)
483 {
484         // get access status
485         uint32_t stat = 0;
486         for(int i = 0; i < 4; i++) {
487                 if(fdc[i].access) {
488                         stat |= 1 << i;
489                 }
490                 fdc[i].access = false;
491         }
492         return stat;
493 }
494
495 void UPD765A::event_callback(int event_id, int err)
496 {
497         if(event_id == EVENT_PHASE) {
498                 phase_id = -1;
499                 phase = event_phase;
500                 process_cmd(command & 0x1f);
501         } else if(event_id == EVENT_DRQ) {
502                 drq_id = -1;
503                 status |= S_RQM;
504                 
505                 int drv = hdu & DRIVE_MASK;
506                 fdc[drv].cur_position = (fdc[drv].cur_position + 1) % disk[drv]->get_track_size();
507                 fdc[drv].prev_clock = prev_drq_clock = get_current_clock();
508                 set_drq(true);
509         } else if(event_id == EVENT_LOST) {
510 //#ifdef _FDC_DEBUG_LOG
511                 if(_fdc_debug_log) this->out_debug_log(_T("FDC: DATA LOST\n"));
512 //#endif
513                 lost_id = -1;
514                 result = ST1_OR;
515                 set_drq(false);
516                 shift_to_result7();
517         } else if(event_id == EVENT_RESULT7) {
518                 result7_id = -1;
519                 shift_to_result7_event();
520         } else if(event_id == EVENT_INDEX) {
521                 // index hole signal width is 5msec (thanks Mr.Sato)
522                 int drv = hdu & DRIVE_MASK;
523                 bool now_index = (disk[drv]->inserted && get_cur_position(drv) < disk[drv]->get_bytes_per_usec(5000));
524                 if(prev_index != now_index) {
525                         write_signals(&outputs_index, now_index ? 0xffffffff : 0);
526                         prev_index = now_index;
527                 }
528         } else if(event_id >= EVENT_SEEK_STEP && event_id < EVENT_SEEK_STEP + 4) {
529                 int drv = event_id - EVENT_SEEK_STEP;
530                 if(fdc[drv].cur_track < fdc[drv].track) {
531                         fdc[drv].cur_track++;
532                         if(d_noise_seek != NULL) d_noise_seek->play();
533                 } else if(fdc[drv].cur_track > fdc[drv].track) {
534                         fdc[drv].cur_track--;
535                         if(d_noise_seek != NULL) d_noise_seek->play();
536                 }
537                 if(fdc[drv].cur_track == fdc[drv].track) {
538                         cancel_event(this, seek_step_id[drv]);
539                         seek_step_id[drv] = -1;
540                 }
541         } else if(event_id >= EVENT_SEEK_END && event_id < EVENT_SEEK_END + 4) {
542                 int drv = event_id - EVENT_SEEK_END;
543                 if(seek_step_id[drv] != -1) {
544                         // to make sure...
545                         cancel_event(this, seek_step_id[drv]);
546                         seek_step_id[drv] = -1;
547                 }
548                 seek_end_id[drv] = -1;
549                 seek_event(drv);
550         } else if(event_id >= EVENT_UNLOAD && event_id < EVENT_UNLOAD + 4) {
551                 int drv = event_id - EVENT_UNLOAD;
552                 if(fdc[drv].head_load) {
553                         if(d_noise_head_up != NULL) d_noise_head_up->play();
554                         fdc[drv].head_load = false;
555                 }
556                 head_unload_id[drv] = -1;
557         }
558 }
559
560 void UPD765A::set_irq(bool val)
561 {
562 //#ifdef _FDC_DEBUG_LOG
563 //      if(_fdc_debug_log) this->out_debug_log(_T("FDC: IRQ=%d\n"), val ? 1 : 0);
564 //#endif
565         write_signals(&outputs_irq, (val && !irq_masked) ? 0xffffffff : 0);
566 }
567
568 void UPD765A::set_drq(bool val)
569 {
570 //#ifdef _FDC_DEBUG_LOG
571 //      if(_fdc_debug_log) this->out_debug_log(_T("FDC: DRQ=%d\n"), val ? 1 : 0);
572 //#endif
573         // cancel next drq and data lost events
574         if(drq_id != -1) {
575                 cancel_event(this, drq_id);
576         }
577         if(lost_id != -1) {
578                 cancel_event(this, lost_id);
579         }
580         drq_id = lost_id = -1;
581         // register data lost event if data exists
582         if(val) {
583 //#ifdef UPD765A_DMA_MODE
584                 // EPSON QC-10 CP/M Plus
585                 if(_upd765a_dma_mode)  {
586                         dma_data_lost = true;
587                 } else {
588 //#else
589                         if((command & 0x1f) != 0x0d) {
590                                 register_event(this, EVENT_LOST, disk[hdu & DRIVE_MASK]->get_usec_per_bytes(1), false, &lost_id);
591                         } else {
592                                 // FIXME: write id
593                                 register_event(this, EVENT_LOST, 30000, false, &lost_id);
594                         }
595                 }
596 //#endif
597         }
598         if(no_dma_mode) {
599                 write_signals(&outputs_irq, (val && !irq_masked) ? 0xffffffff : 0);
600         } else {
601                 write_signals(&outputs_drq, (val && !drq_masked) ? 0xffffffff : 0);
602 //#ifdef UPD765A_DMA_MODE
603                 if(_upd765a_dma_mode)  {
604                 // EPSON QC-10 CP/M Plus
605                         if(val && dma_data_lost) {
606 //#ifdef _FDC_DEBUG_LOG
607                                 if(_fdc_debug_log) this->out_debug_log(_T("FDC: DATA LOST (DMA)\n"));
608 //#endif
609                                 result = ST1_OR;
610                                 write_signals(&outputs_drq, 0);
611                                 shift_to_result7();
612                         }
613                 }
614 //#endif
615         }
616 }
617
618 void UPD765A::set_hdu(uint8_t val)
619 {
620 //#ifdef UPD765A_EXT_DRVSEL
621         if(_upd765a_ext_drvsel) {
622                 hdu = (hdu & 3) | (val & 4);
623         } else {
624 //#else
625                 hdu = val;
626         }
627 //#endif
628         write_signals(&outputs_hdu, hdu);
629 }
630
631 // ----------------------------------------------------------------------------
632 // command
633 // ----------------------------------------------------------------------------
634
635 void UPD765A::process_cmd(int cmd)
636 {
637         switch(cmd & 0x1f) {
638         case 0x02:
639                 cmd_read_diagnostic();
640                 break;
641         case 0x03:
642                 cmd_specify();
643                 break;
644         case 0x04:
645                 cmd_sence_devstat();
646                 break;
647         case 0x05:
648         case 0x09:
649                 cmd_write_data();
650                 break;
651         case 0x06:
652         case 0x0c:
653                 cmd_read_data();
654                 break;
655         case 0x07:
656                 cmd_recalib();
657                 break;
658         case 0x08:
659                 cmd_sence_intstat();
660                 break;
661         case 0x0a:
662                 cmd_read_id();
663                 break;
664         case 0x0d:
665                 cmd_write_id();
666                 break;
667         case 0x0f:
668                 cmd_seek();
669                 break;
670         case 0x11:
671         case 0x19:
672         case 0x1d:
673                 cmd_scan();
674                 break;
675         default:
676                 cmd_invalid();
677                 break;
678         }
679 }
680
681 void UPD765A::cmd_sence_devstat()
682 {
683         switch(phase) {
684         case PHASE_IDLE:
685                 shift_to_cmd(1);
686                 break;
687         case PHASE_CMD:
688                 set_hdu(buffer[0]);
689                 buffer[0] = get_devstat(buffer[0] & DRIVE_MASK);
690                 shift_to_result(1);
691                 break;
692         }
693 }
694
695 void UPD765A::cmd_sence_intstat()
696 {
697         for(int i = 0; i < 4; i++) {
698                 if(fdc[i].result) {
699                         buffer[0] = (uint8_t)fdc[i].result;
700                         buffer[1] = (uint8_t)fdc[i].track;
701                         fdc[i].result = 0;
702                         shift_to_result(2);
703                         return;
704                 }
705         }
706 //#ifdef UPD765A_SENCE_INTSTAT_RESULT
707         // IBM PC/JX
708         if(_upd765a_sence_intstat_result) {
709                 buffer[0] = (uint8_t)ST0_AI;
710         } else {
711 //#else
712                 buffer[0] = (uint8_t)ST0_IC;
713         }
714 //#endif
715         shift_to_result(1);
716 //      status &= ~S_CB;
717 }
718
719 uint8_t UPD765A::get_devstat(int drv)
720 {
721         if(drv >= _max_drive) {
722                 return ST3_FT | drv;
723         }
724         // XM8 version 1.20
725         if(force_ready && !disk[drv]->inserted) {
726                 return drv;
727         }
728         return drv | ((fdc[drv].track & 1) ? ST3_HD : 0) | (disk[drv]->inserted && disk[drv]->two_side ? ST3_TS : 0) | (fdc[drv].track ? 0 : ST3_T0) | (force_ready || disk[drv]->inserted ? ST3_RY : 0) | (disk[drv]->write_protected ? ST3_WP : 0);
729 }
730
731 void UPD765A::cmd_seek()
732 {
733         switch(phase) {
734         case PHASE_IDLE:
735                 shift_to_cmd(2);
736                 break;
737         case PHASE_CMD:
738                 seek(buffer[0] & DRIVE_MASK, buffer[1]);
739                 shift_to_idle();
740                 break;
741         }
742 }
743
744 void UPD765A::cmd_recalib()
745 {
746         switch(phase) {
747         case PHASE_IDLE:
748                 shift_to_cmd(1);
749                 break;
750         case PHASE_CMD:
751                 seek(buffer[0] & DRIVE_MASK, 0);
752                 shift_to_idle();
753                 break;
754         }
755 }
756
757 void UPD765A::seek(int drv, int trk)
758 {
759         // get distance
760         int steptime = (32 - 2 * step_rate_time) * 1000; // msec -> usec
761         if(disk[drv]->drive_type == DRIVE_TYPE_2HD) {
762                 steptime /= 2;
763         }
764         int seektime = (trk == fdc[drv].track) ? 120 : steptime * abs(trk - fdc[drv].track) + 500; // usec
765         
766         if(drv >= _max_drive) {
767                 // invalid drive number
768                 fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR | ST0_AT;
769                 set_irq(true);
770         } else {
771                 fdc[drv].cur_track = fdc[drv].track;
772                 fdc[drv].track = trk;
773 //#ifdef UPD765A_DONT_WAIT_SEEK
774                 if(_upd765a_dont_wait_seek) {
775                         if(fdc[drv].cur_track != fdc[drv].track) {
776                                 if(d_noise_seek != NULL) d_noise_seek->play();
777                         }
778                         seek_event(drv);
779                 } else {
780 //#else
781                         if(seek_step_id[drv] != -1) {
782                                 cancel_event(this, seek_step_id[drv]);
783                         }
784                         if(seek_end_id[drv] != -1) {
785                                 cancel_event(this, seek_end_id[drv]);
786                         }
787                         if(fdc[drv].cur_track != fdc[drv].track) {
788                                 register_event(this, EVENT_SEEK_STEP + drv, steptime, true, &seek_step_id[drv]);
789                         } else {
790                                 seek_step_id[drv] = -1;
791                         }
792                         register_event(this, EVENT_SEEK_END + drv, seektime, false, &seek_end_id[drv]);
793                         seekstat |= 1 << drv;
794                 }
795 //#endif
796         }
797 }
798
799 void UPD765A::seek_event(int drv)
800 {
801         int trk = fdc[drv].track;
802         
803         if(drv >= _max_drive) {
804                 fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR | ST0_AT;
805         } else if(force_ready || disk[drv]->inserted) {
806                 fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE;
807         } else {
808 //#ifdef UPD765A_NO_ST0_AT_FOR_SEEK
809                 if(_upd765a_no_st0_at_for_seek) {
810                         // for NEC PC-100
811                         fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR;
812                 } else {
813 //#else
814                         fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR | ST0_AT;
815                 }
816 //#endif
817         }
818         set_irq(true);
819         seekstat &= ~(1 << drv);
820         
821         // reset dsch flag
822         disk[drv]->changed = false;
823 }
824
825 void UPD765A::cmd_read_data()
826 {
827         switch(phase) {
828         case PHASE_IDLE:
829                 shift_to_cmd(8);
830                 break;
831         case PHASE_CMD:
832                 get_sector_params();
833                 start_transfer();
834                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
835                 break;
836         case PHASE_EXEC:
837                 // XM8 version 1.20
838                 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
839                         REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
840                         break;
841                 }
842                 read_data((command & 0x1f) == 12, false);
843                 break;
844         case PHASE_READ:
845                 if(result) {
846                         shift_to_result7();
847                         break;
848                 }
849                 if(!id_incr()) {
850                         REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
851                         break;
852                 }
853                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
854                 break;
855         case PHASE_TC:
856                 CANCEL_EVENT();
857                 shift_to_result7();
858                 break;
859         case PHASE_TIMER:
860 //              result = ST0_AT | ST1_EN;
861                 result = ST1_EN;
862                 shift_to_result7();
863                 break;
864         }
865 }
866
867 void UPD765A::cmd_write_data()
868 {
869         switch(phase) {
870         case PHASE_IDLE:
871                 shift_to_cmd(8);
872                 break;
873         case PHASE_CMD:
874                 get_sector_params();
875                 start_transfer();
876                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
877                 break;
878         case PHASE_EXEC:
879                 // XM8 version 1.20
880                 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
881                         REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
882                         break;
883                 }
884                 result = check_cond(true);
885                 if(result & ST1_MA) {
886                         REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);      // retry
887                         break;
888                 }
889                 if(!result) {
890                         result = find_id();
891                 }
892                 if(result) {
893                         shift_to_result7();
894                 } else {
895                         int length = 0x80 << (id[3] & 7);
896                         if(!(id[3] & 7)) {
897                                 length = min(dtl, 0x80);
898                                 memset(buffer + length, 0, 0x80 - length);
899                         }
900                         shift_to_write(length);
901                 }
902                 break;
903         case PHASE_WRITE:
904                 write_data((command & 0x1f) == 9);
905                 if(result) {
906                         shift_to_result7();
907                         break;
908                 }
909                 phase = PHASE_EXEC;
910                 if(!id_incr()) {
911                         REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
912                         break;
913                 }
914                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
915                 break;
916         case PHASE_TIMER:
917 //              result = ST0_AT | ST1_EN;
918                 result = ST1_EN;
919                 shift_to_result7();
920                 break;
921         case PHASE_TC:
922                 CANCEL_EVENT();
923                 if(prevphase == PHASE_WRITE && bufptr != buffer) {
924                         // terminate while transfer ?
925                         memset(bufptr, 0, count);
926                         write_data((command & 0x1f) == 9);
927                 }
928                 shift_to_result7();
929                 break;
930         }
931 }
932
933 void UPD765A::cmd_scan()
934 {
935         switch(phase) {
936         case PHASE_IDLE:
937                 shift_to_cmd(9);
938                 break;
939         case PHASE_CMD:
940                 get_sector_params();
941                 dtl = dtl | 0x100;
942                 start_transfer();
943                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
944                 break;
945         case PHASE_EXEC:
946                 // XM8 version 1.20
947                 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
948                         REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
949                         break;
950                 }
951                 read_data(false, true);
952                 break;
953         case PHASE_SCAN:
954                 if(result) {
955                         shift_to_result7();
956                         break;
957                 }
958                 phase = PHASE_EXEC;
959                 if(!id_incr()) {
960                         REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
961                         break;
962                 }
963                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
964                 break;
965         case PHASE_TC:
966                 CANCEL_EVENT();
967                 shift_to_result7();
968                 break;
969         case PHASE_TIMER:
970 //              result = ST0_AT | ST1_EN;
971                 result = ST1_EN;
972                 shift_to_result7();
973                 break;
974         }
975 }
976
977 void UPD765A::cmd_read_diagnostic()
978 {
979         switch(phase) {
980         case PHASE_IDLE:
981                 shift_to_cmd(8);
982                 break;
983         case PHASE_CMD:
984                 get_sector_params();
985                 start_transfer();
986                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
987                 break;
988         case PHASE_EXEC:
989                 // XM8 version 1.20
990                 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
991                         REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
992                         break;
993                 }
994                 read_diagnostic();
995                 break;
996         case PHASE_READ:
997                 if(result & ~ST1_ND) {
998                         shift_to_result7();
999                         break;
1000                 }
1001                 if(!id_incr()) {
1002                         REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
1003                         break;
1004                 }
1005                 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
1006                 break;
1007         case PHASE_TC:
1008                 CANCEL_EVENT();
1009                 shift_to_result7();
1010                 break;
1011         case PHASE_TIMER:
1012 //              result |= ST0_AT | ST1_EN;
1013                 result |= ST1_EN;
1014                 shift_to_result7();
1015                 break;
1016         }
1017 }
1018
1019 void UPD765A::read_data(bool deleted, bool scan)
1020 {
1021         result = check_cond(false);
1022         if(result & ST1_MA) {
1023                 REGISTER_PHASE_EVENT(PHASE_EXEC, 10000);
1024                 return;
1025         }
1026         if(result) {
1027                 shift_to_result7();
1028                 return;
1029         }
1030         result = read_sector();
1031         if(deleted) {
1032                 result ^= ST2_CM;
1033         }
1034         if((result & ~ST2_CM) && !(result & ST2_DD)) {
1035                 shift_to_result7();
1036                 return;
1037         }
1038         if((result & ST2_CM) && (command & 0x20)) {
1039                 REGISTER_PHASE_EVENT(PHASE_TIMER, 100000);
1040                 return;
1041         }
1042         int length = (id[3] & 7) ? (0x80 << (id[3] & 7)) : (min(dtl, 0x80));
1043         if(!scan) {
1044                 shift_to_read(length);
1045         } else {
1046                 shift_to_scan(length);
1047         }
1048         return;
1049 }
1050
1051 void UPD765A::write_data(bool deleted)
1052 {
1053         if((result = check_cond(true)) != 0) {
1054                 shift_to_result7();
1055                 return;
1056         }
1057         result = write_sector(deleted);
1058         return;
1059 }
1060
1061 void UPD765A::read_diagnostic()
1062 {
1063         int drv = hdu & DRIVE_MASK;
1064         int trk = fdc[drv].track;
1065         int side = (hdu >> 2) & 1;
1066         
1067         result = check_cond(false);
1068         if(result & ST1_MA) {
1069                 REGISTER_PHASE_EVENT(PHASE_EXEC, 10000);
1070                 return;
1071         }
1072         if(result) {
1073                 shift_to_result7();
1074                 return;
1075         }
1076         if(!disk[drv]->make_track(trk, side)) {
1077 //              result = ST1_ND;
1078                 result = ST0_AT | ST1_MA;
1079                 shift_to_result7();
1080                 return;
1081         }
1082         if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1083 //              result = ST1_ND;
1084                 result = ST0_AT | ST1_MA;
1085                 shift_to_result7();
1086                 return;
1087         }
1088         if(disk[drv]->get_sector(trk, side, 0)) {
1089 #if 0
1090                 if(disk[drv]->id[0] != id[0] || disk[drv]->id[1] != id[1] || disk[drv]->id[2] != id[2] /*|| disk[drv]->id[3] != id[3]*/) {
1091 #else
1092                 if(disk[drv]->id[0] != id[0] || disk[drv]->id[1] != id[1] || disk[drv]->id[2] != id[2] || disk[drv]->id[3] != id[3]) {
1093 #endif
1094                         result = ST1_ND;
1095                 }
1096         }
1097         
1098         // FIXME: we need to consider the case that the first sector does not have a data field
1099         // start reading at the first sector data
1100         memcpy(buffer, disk[drv]->track + disk[drv]->data_position[0], disk[drv]->get_track_size() - disk[drv]->data_position[0]);
1101         memcpy(buffer + disk[drv]->get_track_size() - disk[drv]->data_position[0], disk[drv]->track, disk[drv]->data_position[0]);
1102         fdc[drv].next_trans_position = disk[drv]->data_position[0];
1103         
1104         shift_to_read(0x80 << (id[3] & 7));
1105         return;
1106 }
1107
1108 uint32_t UPD765A::read_sector()
1109 {
1110         int drv = hdu & DRIVE_MASK;
1111         int trk = fdc[drv].track;
1112         int side = (hdu >> 2) & 1;
1113         
1114         // get sector counts in the current track
1115         if(!disk[drv]->make_track(trk, side)) {
1116 //#ifdef _FDC_DEBUG_LOG
1117                 if(_fdc_debug_log) this->out_debug_log(_T("FDC: TRACK NOT FOUND (TRK=%d SIDE=%d)\n"), trk, side);
1118 //#endif
1119                 return ST0_AT | ST1_MA;
1120         }
1121         if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1122                 return ST0_AT | ST1_MA;
1123         }
1124         int secnum = disk[drv]->sector_num.sd;
1125         if(!secnum) {
1126 //#ifdef _FDC_DEBUG_LOG
1127                 if(_fdc_debug_log) this->out_debug_log(_T("FDC: NO SECTORS IN TRACK (TRK=%d SIDE=%d)\n"), trk, side);
1128 //#endif
1129                 return ST0_AT | ST1_MA;
1130         }
1131         int cy = -1;
1132         for(int i = 0; i < secnum; i++) {
1133                 if(!disk[drv]->get_sector(trk, side, i)) {
1134                         continue;
1135                 }
1136                 cy = disk[drv]->id[0];
1137 #if 0
1138                 if(disk[drv]->id[0] != id[0] || disk[drv]->id[1] != id[1] || disk[drv]->id[2] != id[2] /*|| disk[drv]->id[3] != id[3]*/) {
1139 #else
1140                 if(disk[drv]->id[0] != id[0] || disk[drv]->id[1] != id[1] || disk[drv]->id[2] != id[2] || disk[drv]->id[3] != id[3]) {
1141 #endif
1142                         continue;
1143                 }
1144 #ifdef _FDC_DEBUG_LOG
1145                 this->out_debug_log(_T("FDC: SECTOR FOUND (TRK=%d SIDE=%d ID=%2x,%2x,%2x,%2x)\n"), trk, side, id[0], id[1], id[2], id[3]);
1146 #endif
1147                 if(disk[drv]->sector_size.sd == 0) {
1148                         continue;
1149                 }
1150                 // sector number is matched
1151                 if(disk[drv]->invalid_format) {
1152                         memset(buffer, disk[drv]->drive_mfm ? 0x4e : 0xff, sizeof(buffer));
1153                         memcpy(buffer, disk[drv]->sector, disk[drv]->sector_size.sd);
1154                 } else {
1155                         memcpy(buffer, disk[drv]->track + disk[drv]->data_position[i], disk[drv]->get_track_size() - disk[drv]->data_position[i]);
1156                         memcpy(buffer + disk[drv]->get_track_size() - disk[drv]->data_position[i], disk[drv]->track, disk[drv]->data_position[i]);
1157                 }
1158                 fdc[drv].next_trans_position = disk[drv]->data_position[i];
1159                 
1160                 if((disk[drv]->addr_crc_error || disk[drv]->data_crc_error) && !disk[drv]->ignore_crc()) {
1161                         return ST0_AT | ST1_DE | (disk[drv]->data_crc_error ? ST2_DD : 0);
1162                 }
1163                 if(disk[drv]->deleted) {
1164                         return ST2_CM;
1165                 }
1166                 return 0;
1167         }
1168 //#ifdef _FDC_DEBUG_LOG
1169         if(_fdc_debug_log) this->out_debug_log(_T("FDC: SECTOR NOT FOUND (TRK=%d SIDE=%d ID=%2x,%2x,%2x,%2x)\n"), trk, side, id[0], id[1], id[2], id[3]);
1170 //#endif
1171         if(cy != id[0] && cy != -1) {
1172                 if(cy == 0xff) {
1173                         return ST0_AT | ST1_ND | ST2_BC;
1174                 } else {
1175                         return ST0_AT | ST1_ND | ST2_NC;
1176                 }
1177         }
1178         return ST0_AT | ST1_ND;
1179 }
1180
1181 uint32_t UPD765A::write_sector(bool deleted)
1182 {
1183         int drv = hdu & DRIVE_MASK;
1184         int trk = fdc[drv].track;
1185         int side = (hdu >> 2) & 1;
1186         
1187         if(disk[drv]->write_protected) {
1188                 return ST0_AT | ST1_NW;
1189         }
1190         // get sector counts in the current track
1191         if(!disk[drv]->get_track(trk, side)) {
1192                 return ST0_AT | ST1_MA;
1193         }
1194         int secnum = disk[drv]->sector_num.sd;
1195         if(!secnum) {
1196                 return ST0_AT | ST1_MA;
1197         }
1198         int cy = -1;
1199         for(int i = 0; i < secnum; i++) {
1200                 if(!disk[drv]->get_sector(trk, side, i)) {
1201                         continue;
1202                 }
1203                 cy = disk[drv]->id[0];
1204                 if(disk[drv]->id[0] != id[0] || disk[drv]->id[1] != id[1] || disk[drv]->id[2] != id[2] /*|| disk[drv]->id[3] != id[3]*/) {
1205                         continue;
1206                 }
1207                 if(disk[drv]->sector_size.sd == 0) {
1208                         continue;
1209                 }
1210                 // sector number is matched
1211                 int size = 0x80 << (id[3] & 7);
1212                 memcpy(disk[drv]->sector, buffer, min(size, disk[drv]->sector_size.sd));
1213                 disk[drv]->set_deleted(deleted);
1214                 return 0;
1215         }
1216         if(cy != id[0] && cy != -1) {
1217                 if(cy == 0xff) {
1218                         return ST0_AT | ST1_ND | ST2_BC;
1219                 } else {
1220                         return ST0_AT | ST1_ND | ST2_NC;
1221                 }
1222         }
1223         return ST0_AT | ST1_ND;
1224 }
1225
1226 uint32_t UPD765A::find_id()
1227 {
1228         int drv = hdu & DRIVE_MASK;
1229         int trk = fdc[drv].track;
1230         int side = (hdu >> 2) & 1;
1231         
1232         // get sector counts in the current track
1233         if(!disk[drv]->get_track(trk, side)) {
1234                 return ST0_AT | ST1_MA;
1235         }
1236         if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1237                 return ST0_AT | ST1_MA;
1238         }
1239         int secnum = disk[drv]->sector_num.sd;
1240         if(!secnum) {
1241                 return ST0_AT | ST1_MA;
1242         }
1243         int cy = -1;
1244         for(int i = 0; i < secnum; i++) {
1245                 if(!disk[drv]->get_sector(trk, side, i)) {
1246                         continue;
1247                 }
1248                 cy = disk[drv]->id[0];
1249                 if(disk[drv]->id[0] != id[0] || disk[drv]->id[1] != id[1] || disk[drv]->id[2] != id[2] /*|| disk[drv]->id[3] != id[3]*/) {
1250                         continue;
1251                 }
1252                 if(disk[drv]->sector_size.sd == 0) {
1253                         continue;
1254                 }
1255                 // sector number is matched
1256                 fdc[drv].next_trans_position = disk[drv]->data_position[i];
1257                 return 0;
1258         }
1259         if(cy != id[0] && cy != -1) {
1260                 if(cy == 0xff) {
1261                         return ST0_AT | ST1_ND | ST2_BC;
1262                 } else {
1263                         return ST0_AT | ST1_ND | ST2_NC;
1264                 }
1265         }
1266         return ST0_AT | ST1_ND;
1267 }
1268
1269 uint32_t UPD765A::check_cond(bool write)
1270 {
1271         int drv = hdu & DRIVE_MASK;
1272         hdue = hdu;
1273         if(drv >= _max_drive) {
1274                 return ST0_AT | ST0_NR;
1275         }
1276         if(!disk[drv]->inserted) {
1277                 return ST0_AT | ST1_MA;
1278         }
1279         return 0;
1280 }
1281
1282 void UPD765A::get_sector_params()
1283 {
1284         set_hdu(buffer[0]);
1285         hdue = buffer[0];
1286         id[0] = buffer[1];
1287         id[1] = buffer[2];
1288         id[2] = buffer[3];
1289         id[3] = buffer[4];
1290         eot = buffer[5];
1291         gpl = buffer[6];
1292         dtl = buffer[7];
1293 }
1294
1295 bool UPD765A::id_incr()
1296 {
1297         if((command & 19) == 17) {
1298                 // scan equal
1299                 if((dtl & 0xff) == 0x02) {
1300                         id[2]++;
1301                 }
1302         }
1303         if(id[2]++ != eot) {
1304                 return true;
1305         }
1306         id[2] = 1;
1307         if(command & 0x80) {
1308                 set_hdu(hdu ^ 4);
1309                 id[1] ^= 1;
1310                 if(id[1] & 1) {
1311                         return true;
1312                 }
1313         }
1314         id[0]++;
1315         return false;
1316 }
1317
1318 void UPD765A::cmd_read_id()
1319 {
1320         switch(phase) {
1321         case PHASE_IDLE:
1322                 shift_to_cmd(1);
1323                 break;
1324         case PHASE_CMD:
1325                 set_hdu(buffer[0]);
1326                 start_transfer();
1327 //              break;
1328         case PHASE_EXEC:
1329                 // XM8 version 1.20
1330                 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
1331                         REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
1332                         break;
1333                 }
1334                 if(check_cond(false) & ST1_MA) {
1335 //                      REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
1336 //                      break;
1337                 }
1338                 if((result = read_id()) == 0) {
1339                         int drv = hdu & DRIVE_MASK;
1340                         int bytes = fdc[drv].next_trans_position - get_cur_position(drv);
1341                         if(bytes < 0) {
1342                                 bytes += disk[drv]->get_track_size();
1343                         }
1344                         REGISTER_PHASE_EVENT_NEW(PHASE_TIMER, disk[drv]->get_usec_per_bytes(bytes));
1345                 } else {
1346                         REGISTER_PHASE_EVENT(PHASE_TIMER, 5000);
1347                 }
1348                 break;
1349         case PHASE_TIMER:
1350                 shift_to_result7();
1351                 break;
1352         }
1353 }
1354
1355 void UPD765A::cmd_write_id()
1356 {
1357         switch(phase) {
1358         case PHASE_IDLE:
1359                 shift_to_cmd(5);
1360                 break;
1361         case PHASE_CMD:
1362                 set_hdu(buffer[0]);
1363                 id[3] = buffer[1];
1364                 eot = buffer[2];
1365                 gpl = buffer[3];
1366                 dtl = buffer[4]; // temporary
1367                 if(!eot) {
1368                         REGISTER_PHASE_EVENT(PHASE_TIMER, 1000000);
1369                         break;
1370                 }
1371                 start_transfer();
1372                 fdc[hdu & DRIVE_MASK].next_trans_position = get_cur_position(hdu & DRIVE_MASK);
1373                 shift_to_write(4 * eot);
1374                 break;
1375         case PHASE_TC:
1376         case PHASE_WRITE:
1377                 REGISTER_PHASE_EVENT(PHASE_TIMER, 4000000);
1378                 break;
1379         case PHASE_TIMER:
1380                 // XM8 version 1.20
1381                 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
1382                         REGISTER_PHASE_EVENT(PHASE_TIMER, 1000000);
1383                         break;
1384                 }
1385                 result =  write_id();
1386                 shift_to_result7();
1387                 break;
1388         }
1389 }
1390
1391 uint32_t UPD765A::read_id()
1392 {
1393         int drv = hdu & DRIVE_MASK;
1394         int trk = fdc[drv].track;
1395         int side = (hdu >> 2) & 1;
1396         
1397         // get sector counts in the current track
1398         if(!disk[drv]->get_track(trk, side)) {
1399                 return ST0_AT | ST1_MA;
1400         }
1401         if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1402                 return ST0_AT | ST1_MA;
1403         }
1404         int secnum = disk[drv]->sector_num.sd;
1405         if(!secnum) {
1406                 return ST0_AT | ST1_MA;
1407         }
1408         
1409         // first found sector
1410         int position = get_cur_position(drv), first_sector = 0;
1411         if(position > disk[drv]->sync_position[secnum - 1]) {
1412                 position -= disk[drv]->get_track_size();
1413         }
1414         for(int i = 0; i < secnum; i++) {
1415                 if(position < disk[drv]->sync_position[i]) {
1416                         first_sector = i;
1417                         break;
1418                 }
1419         }
1420         for(int i = 0; i < secnum; i++) {
1421                 int index = (first_sector + i) % secnum;
1422                 if(disk[drv]->get_sector(trk, side, index)) {
1423                         id[0] = disk[drv]->id[0];
1424                         id[1] = disk[drv]->id[1];
1425                         id[2] = disk[drv]->id[2];
1426                         id[3] = disk[drv]->id[3];
1427                         fdc[drv].next_trans_position = disk[drv]->id_position[index] + 6;
1428                         return 0;
1429                 }
1430         }
1431         return ST0_AT | ST1_ND;
1432 }
1433
1434 uint32_t UPD765A::write_id()
1435 {
1436         int drv = hdu & DRIVE_MASK;
1437         int trk = fdc[drv].track;
1438         int side = (hdu >> 2) & 1;
1439         int length = 0x80 << (id[3] & 7);
1440         
1441         if((result = check_cond(true)) != 0) {
1442                 return result;
1443         }
1444         if(disk[drv]->write_protected) {
1445                 return ST0_AT | ST1_NW;
1446         }
1447         
1448         disk[drv]->format_track(trk, side);
1449         disk[drv]->track_mfm = ((command & 0x40) != 0);
1450         
1451         for(int i = 0; i < eot && i < 256; i++) {
1452                 for(int j = 0; j < 4; j++) {
1453                         id[j] = buffer[4 * i + j];
1454                 }
1455                 disk[drv]->insert_sector(id[0], id[1], id[2], id[3], false, false, dtl, length);
1456         }
1457         return 0;
1458 }
1459
1460 void UPD765A::cmd_specify()
1461 {
1462         switch(phase) {
1463         case PHASE_IDLE:
1464                 shift_to_cmd(2);
1465                 break;
1466         case PHASE_CMD:
1467                 step_rate_time = buffer[0] >> 4;
1468                 head_unload_time = buffer[1] >> 1;
1469                 no_dma_mode = ((buffer[1] & 1) != 0);
1470                 shift_to_idle();
1471                 status = 0x80;//0xff;
1472                 break;
1473         }
1474 }
1475
1476 void UPD765A::cmd_invalid()
1477 {
1478         buffer[0] = (uint8_t)ST0_IC;
1479         shift_to_result(1);
1480 }
1481
1482 void UPD765A::shift_to_idle()
1483 {
1484         phase = PHASE_IDLE;
1485         status = S_RQM;
1486 }
1487
1488 void UPD765A::shift_to_cmd(int length)
1489 {
1490         phase = PHASE_CMD;
1491         status = S_RQM | S_CB;
1492         bufptr = buffer;
1493         count = length;
1494 }
1495
1496 void UPD765A::shift_to_exec()
1497 {
1498         phase = PHASE_EXEC;
1499         process_cmd(command & 0x1f);
1500 }
1501
1502 void UPD765A::shift_to_read(int length)
1503 {
1504         phase = PHASE_READ;
1505         status = S_RQM | S_DIO | S_NDM | S_CB;
1506         bufptr = buffer;
1507         count = length;
1508         
1509         int drv = hdu & DRIVE_MASK;
1510         fdc[drv].cur_position = fdc[drv].next_trans_position;
1511         fdc[drv].prev_clock = prev_drq_clock = get_current_clock();
1512         set_drq(true);
1513 }
1514
1515 void UPD765A::shift_to_write(int length)
1516 {
1517         phase = PHASE_WRITE;
1518         status = S_RQM | S_NDM | S_CB;
1519         bufptr = buffer;
1520         count = length;
1521         
1522         int drv = hdu & DRIVE_MASK;
1523         fdc[drv].cur_position = fdc[drv].next_trans_position;
1524         fdc[drv].prev_clock = prev_drq_clock = get_current_clock();
1525         set_drq(true);
1526 }
1527
1528 void UPD765A::shift_to_scan(int length)
1529 {
1530         phase = PHASE_SCAN;
1531         status = S_RQM | S_NDM | S_CB;
1532         result = ST2_SH;
1533         bufptr = buffer;
1534         count = length;
1535         
1536         int drv = hdu & DRIVE_MASK;
1537         fdc[drv].cur_position = fdc[drv].next_trans_position;
1538         fdc[drv].prev_clock = prev_drq_clock = get_current_clock();
1539         set_drq(true);
1540 }
1541
1542 void UPD765A::shift_to_result(int length)
1543 {
1544         phase = PHASE_RESULT;
1545         status = S_RQM | S_CB | S_DIO;
1546         bufptr = buffer;
1547         count = length;
1548 }
1549
1550 void UPD765A::shift_to_result7()
1551 {
1552 //#ifdef UPD765A_WAIT_RESULT7
1553         if(_upd765a_wait_result7) {
1554                 if(result7_id != -1) {
1555                         cancel_event(this, result7_id);
1556                         result7_id = -1;
1557                 }
1558                 if(phase != PHASE_TIMER) {
1559                         register_event(this, EVENT_RESULT7, 100, false, &result7_id);
1560                 } else {
1561 //#endif
1562                         shift_to_result7_event();
1563                 }
1564         } else {
1565                 shift_to_result7_event();
1566         }               
1567         finish_transfer();
1568 }
1569
1570 void UPD765A::shift_to_result7_event()
1571 {
1572 //#ifdef UPD765A_NO_ST1_EN_OR_FOR_RESULT7
1573         // for NEC PC-9801 (XANADU)
1574         if(_upd765a_no_st1_en_or_for_result7) result &= ~(ST1_EN | ST1_OR);
1575 //#endif
1576         buffer[0] = (result & 0xf8) | (hdue & 7);
1577         buffer[1] = uint8_t(result >>  8);
1578         buffer[2] = uint8_t(result >> 16);
1579         buffer[3] = id[0];
1580         buffer[4] = id[1];
1581         buffer[5] = id[2];
1582         buffer[6] = id[3];
1583         set_irq(true);
1584         shift_to_result(7);
1585 }
1586
1587 void UPD765A::start_transfer()
1588 {
1589         int drv = hdu & DRIVE_MASK;
1590         
1591         if(head_unload_id[drv] != -1) {
1592                 cancel_event(this, head_unload_id[drv]);
1593                 head_unload_id[drv] = -1;
1594         }
1595         if(!fdc[drv].head_load) {
1596                 if(d_noise_head_down != NULL) d_noise_head_down->play();
1597                 fdc[drv].head_load = true;
1598         }
1599 }
1600
1601 void UPD765A::finish_transfer()
1602 {
1603         int drv = hdu & DRIVE_MASK;
1604         
1605         if(fdc[drv].head_load) {
1606                 if(head_unload_id[drv] != -1) {
1607                         cancel_event(this, head_unload_id[drv]);
1608                 }
1609                 int time = (16 * (head_unload_time + 1)) * 1000; // msec -> usec
1610                 if(disk[drv]->drive_type == DRIVE_TYPE_2HD) {
1611                         time /= 2;
1612                 }
1613                 register_event(this, EVENT_UNLOAD + drv, time, false, &head_unload_id[drv]);
1614         }
1615 }
1616
1617 // ----------------------------------------------------------------------------
1618 // timing
1619 // ----------------------------------------------------------------------------
1620
1621 int UPD765A::get_cur_position(int drv)
1622 {
1623         return (fdc[drv].cur_position + disk[drv]->get_bytes_per_usec(get_passed_usec(fdc[drv].prev_clock))) % disk[drv]->get_track_size();
1624 }
1625
1626 double UPD765A::get_usec_to_exec_phase()
1627 {
1628         int drv = hdu & DRIVE_MASK;
1629         int trk = fdc[drv].track;
1630         int side = (hdu >> 2) & 1;
1631         
1632         if(/*disk[drv]->no_skew &&*/ !disk[drv]->correct_timing()) {
1633                 // XXX: this image may be a standard image or coverted from a standard image and skew may be incorrect,
1634                 // so use the constant period to go to exec phase
1635                 return 100;
1636         }
1637         
1638         // search target sector
1639         int position = get_cur_position(drv);
1640         int trans_position = -1, sync_position;
1641         
1642         if(disk[drv]->get_track(trk, side) && disk[drv]->sector_num.sd != 0) {
1643                 if((command & 0x1f) == 0x02) {
1644                         // read diagnotics
1645                         trans_position = disk[drv]->data_position[0];
1646                         sync_position = disk[drv]->sync_position[0];
1647                 } else {
1648                         for(int i = 0; i < disk[drv]->sector_num.sd; i++) {
1649                                 if(!disk[drv]->get_sector(trk, side, i)) {
1650                                         continue;
1651                                 }
1652                                 if(disk[drv]->id[0] != id[0] || disk[drv]->id[1] != id[1] || disk[drv]->id[2] != id[2] /*|| disk[drv]->id[3] != id[3]*/) {
1653                                         continue;
1654                                 }
1655                                 // sector number is matched
1656                                 trans_position = disk[drv]->data_position[i];
1657                                 sync_position = disk[drv]->sync_position[i];
1658                                 break;
1659                         }
1660                 }
1661         }
1662         if(trans_position == -1) {
1663                 // sector not found
1664                 return 100;
1665         }
1666         
1667         // get current position
1668         int bytes = trans_position - position;
1669         if(sync_position < position) {
1670                 bytes += disk[drv]->get_track_size();
1671         }
1672         return disk[drv]->get_usec_per_bytes(bytes);
1673 }
1674
1675 // ----------------------------------------------------------------------------
1676 // user interface
1677 // ----------------------------------------------------------------------------
1678
1679 void UPD765A::open_disk(int drv, const _TCHAR* file_path, int bank)
1680 {
1681         if(drv < _max_drive) {
1682                 disk[drv]->open(file_path, bank);
1683                 if(disk[drv]->changed) {
1684 //#ifdef _FDC_DEBUG_LOG
1685                         if(_fdc_debug_log) this->out_debug_log(_T("FDC: Disk Changed (Drive=%d)\n"), drv);
1686 //#endif
1687                         if(raise_irq_when_media_changed) {
1688                                 fdc[drv].result = (drv & DRIVE_MASK) | ST0_AI | ST0_NR;
1689                                 set_irq(true);
1690                         }
1691                 }
1692         }
1693 }
1694
1695 void UPD765A::close_disk(int drv)
1696 {
1697         if(drv < _max_drive && disk[drv]->inserted) {
1698                 if(fdc[drv].head_load) {
1699                         if(d_noise_head_up != NULL) d_noise_head_up->play();
1700                         fdc[drv].head_load = false;
1701                 }
1702                 disk[drv]->close();
1703 //#ifdef _FDC_DEBUG_LOG
1704                 if(_fdc_debug_log) this->out_debug_log(_T("FDC: Disk Ejected (Drive=%d)\n"), drv);
1705 //#endif
1706                 if(raise_irq_when_media_changed) {
1707                         fdc[drv].result = (drv & DRIVE_MASK) | ST0_AI;
1708                         set_irq(true);
1709                 }
1710         }
1711 }
1712
1713 bool UPD765A::is_disk_inserted(int drv)
1714 {
1715         if(drv < _max_drive) {
1716                 return disk[drv]->inserted;
1717         }
1718         return false;
1719 }
1720
1721 bool UPD765A::is_disk_inserted()
1722 {
1723         int drv = hdu & DRIVE_MASK;
1724         return is_disk_inserted(drv);
1725 }
1726
1727 bool UPD765A::disk_ejected(int drv)
1728 {
1729         if(drv < _max_drive) {
1730                 return disk[drv]->ejected;
1731         }
1732         return false;
1733 }
1734
1735 bool UPD765A::disk_ejected()
1736 {
1737         int drv = hdu & DRIVE_MASK;
1738         return disk_ejected(drv);
1739 }
1740
1741 void UPD765A::is_disk_protected(int drv, bool value)
1742 {
1743         if(drv < _max_drive) {
1744                 disk[drv]->write_protected = value;
1745         }
1746 }
1747
1748 bool UPD765A::is_disk_protected(int drv)
1749 {
1750         if(drv < _max_drive) {
1751                 return disk[drv]->write_protected;
1752         }
1753         return false;
1754 }
1755
1756 uint8_t UPD765A::get_media_type(int drv)
1757 {
1758         if(drv < _max_drive && disk[drv]->inserted) {
1759                 return disk[drv]->media_type;
1760         }
1761         return MEDIA_TYPE_UNK;
1762 }
1763
1764 void UPD765A::set_drive_type(int drv, uint8_t type)
1765 {
1766         if(drv < _max_drive) {
1767                 disk[drv]->drive_type = type;
1768         }
1769 }
1770
1771 uint8_t UPD765A::get_drive_type(int drv)
1772 {
1773         if(drv < _max_drive) {
1774                 return disk[drv]->drive_type;
1775         }
1776         return DRIVE_TYPE_UNK;
1777 }
1778
1779 void UPD765A::set_drive_rpm(int drv, int rpm)
1780 {
1781         if(drv < _max_drive) {
1782                 disk[drv]->drive_rpm = rpm;
1783         }
1784 }
1785
1786 void UPD765A::set_drive_mfm(int drv, bool mfm)
1787 {
1788         if(drv < _max_drive) {
1789                 disk[drv]->drive_mfm = mfm;
1790         }
1791 }
1792
1793 void UPD765A::update_config()
1794 {
1795         if(d_noise_seek != NULL) {
1796                 d_noise_seek->set_mute(!config.sound_noise_fdd);
1797         }
1798         if(d_noise_head_down != NULL) {
1799                 d_noise_head_down->set_mute(!config.sound_noise_fdd);
1800         }
1801         if(d_noise_head_up != NULL) {
1802                 d_noise_head_up->set_mute(!config.sound_noise_fdd);
1803         }
1804         _fdc_debug_log = config.special_debug_fdc;
1805 }
1806
1807 //#ifdef USE_DEBUGGER
1808 void UPD765A::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
1809 {
1810         int drv = hdu & DRIVE_MASK;
1811         int side = (hdu >> 2) & 1;
1812         
1813         my_stprintf_s(buffer, buffer_len,
1814         _T("CMD=%02X (%s) HDU=%02X C=%02X H=%02X R=%02X N=%02X EOT=%02X GPL=%02X DTL=%02X\nUNIT: DRIVE=%d TRACK=%2d(%2d) SIDE=%d SECTORS=%2d C=%02X H=%02X R=%02X N=%02X LENGTH=%d"),
1815         command, get_command_name(command), hdu,id[0], id[1], id[2], id[3], eot, gpl, dtl,
1816         drv, fdc[drv].track, fdc[drv].cur_track, side, disk[drv]->sector_num.sd,
1817         disk[drv]->id[0], disk[drv]->id[1], disk[drv]->id[2], disk[drv]->id[3],
1818         disk[drv]->sector_size.sd);
1819 }
1820 //#endif
1821
1822 #define STATE_VERSION   3
1823
1824 #include "../statesub.h"
1825
1826 void UPD765A::decl_state_fdc(int ch)
1827 {
1828         DECL_STATE_ENTRY_UINT8_MEMBER((fdc[ch].track), ch);
1829         DECL_STATE_ENTRY_UINT8_MEMBER((fdc[ch].cur_track), ch);
1830         DECL_STATE_ENTRY_UINT8_MEMBER((fdc[ch].result), ch);
1831         
1832         DECL_STATE_ENTRY_BOOL_MEMBER((fdc[ch].access), ch);
1833         DECL_STATE_ENTRY_BOOL_MEMBER((fdc[ch].head_load), ch);
1834
1835         DECL_STATE_ENTRY_INT32_MEMBER((fdc[ch].cur_position), ch);
1836         DECL_STATE_ENTRY_INT32_MEMBER((fdc[ch].next_trans_position), ch);
1837
1838         DECL_STATE_ENTRY_UINT32_MEMBER((fdc[ch].prev_clock), ch);
1839
1840 }
1841
1842 void UPD765A::decl_state()
1843 {
1844         enter_decl_state(STATE_VERSION);
1845
1846         for(int i = 0; i < 4; i++) {
1847                 decl_state_fdc(i);
1848         }
1849         
1850         DECL_STATE_ENTRY_UINT8(hdu);
1851         DECL_STATE_ENTRY_UINT8(hdue);
1852         DECL_STATE_ENTRY_1D_ARRAY(id, sizeof(id));
1853         
1854         DECL_STATE_ENTRY_UINT8(eot);
1855         DECL_STATE_ENTRY_UINT8(gpl);
1856         DECL_STATE_ENTRY_UINT8(dtl);
1857         DECL_STATE_ENTRY_INT32(phase);
1858         DECL_STATE_ENTRY_INT32(prevphase);
1859         DECL_STATE_ENTRY_UINT8(status);
1860         DECL_STATE_ENTRY_UINT8(seekstat);
1861         DECL_STATE_ENTRY_UINT8(command);
1862         DECL_STATE_ENTRY_UINT32(result);
1863         DECL_STATE_ENTRY_INT32(step_rate_time);
1864         DECL_STATE_ENTRY_INT32(head_unload_time);
1865         DECL_STATE_ENTRY_BOOL(no_dma_mode);
1866         DECL_STATE_ENTRY_BOOL(motor_on);
1867 //#ifdef UPD765A_DMA_MODE
1868         if(_upd765a_dma_mode) DECL_STATE_ENTRY_BOOL(dma_data_lost);
1869 //#endif
1870         DECL_STATE_ENTRY_BOOL(irq_masked);
1871         DECL_STATE_ENTRY_BOOL(drq_masked);
1872         
1873         DECL_STATE_ENTRY_INT32(tmp_bufsize);
1874         DECL_STATE_ENTRY_1D_ARRAY(buffer, sizeof(buffer));
1875         
1876         DECL_STATE_ENTRY_INT32(count);
1877         DECL_STATE_ENTRY_INT32(event_phase);
1878         DECL_STATE_ENTRY_INT32(phase_id);
1879         DECL_STATE_ENTRY_INT32(drq_id);
1880         DECL_STATE_ENTRY_INT32(lost_id);
1881         DECL_STATE_ENTRY_INT32(result7_id);
1882         DECL_STATE_ENTRY_1D_ARRAY(seek_step_id, sizeof(seek_step_id) / sizeof(int));
1883         DECL_STATE_ENTRY_1D_ARRAY(seek_end_id, sizeof(seek_end_id) / sizeof(int));
1884         DECL_STATE_ENTRY_1D_ARRAY(head_unload_id, sizeof(head_unload_id) / sizeof(int));
1885         DECL_STATE_ENTRY_BOOL(force_ready);
1886         DECL_STATE_ENTRY_BOOL(reset_signal);
1887         DECL_STATE_ENTRY_BOOL(prev_index);
1888         DECL_STATE_ENTRY_UINT32(prev_drq_clock);
1889
1890         for(int i = 0; i < 4; i++) {
1891                 disk[i]->decl_state(p_logger);
1892         }
1893         leave_decl_state();
1894 }
1895 void UPD765A::save_state(FILEIO* state_fio)
1896 {
1897         tmp_bufsize = (int)(bufptr - buffer);
1898
1899         if(state_entry != NULL) {
1900                 state_entry->save_state(state_fio);
1901         }
1902         
1903 //      state_fio->FputUint32(STATE_VERSION);
1904 //      state_fio->FputInt32(this_device_id);
1905         
1906 //      state_fio->Fwrite(fdc, sizeof(fdc), 1);
1907         for(int i = 0; i < 4; i++) {
1908                 disk[i]->save_state(state_fio);
1909         }
1910 //      state_fio->FputUint8(hdu);
1911 //      state_fio->FputUint8(hdue);
1912 //      state_fio->Fwrite(id, sizeof(id), 1);
1913 //      state_fio->FputUint8(eot);
1914 //      state_fio->FputUint8(gpl);
1915 //      state_fio->FputUint8(dtl);
1916 //      state_fio->FputInt32(phase);
1917 //      state_fio->FputInt32(prevphase);
1918 //      state_fio->FputUint8(status);
1919 //      state_fio->FputUint8(seekstat);
1920 //      state_fio->FputUint8(command);
1921 //      state_fio->FputUint32(result);
1922 //      state_fio->FputInt32(step_rate_time);
1923 //      state_fio->FputInt32(head_unload_time);
1924 //      state_fio->FputBool(no_dma_mode);
1925 //      state_fio->FputBool(motor_on);
1926 //#ifdef UPD765A_DMA_MODE
1927 //      if(_upd765a_dma_mode) state_fio->FputBool(dma_data_lost);
1928 //#endif
1929 //      state_fio->FputBool(irq_masked);
1930 //      state_fio->FputBool(drq_masked);
1931 //      state_fio->FputInt32((int)(bufptr - buffer));
1932 //      state_fio->Fwrite(buffer, sizeof(buffer), 1);
1933 //      state_fio->FputInt32(count);
1934 //      state_fio->FputInt32(event_phase);
1935 //      state_fio->FputInt32(phase_id);
1936 //      state_fio->FputInt32(drq_id);
1937 //      state_fio->FputInt32(lost_id);
1938 //      state_fio->FputInt32(result7_id);
1939 //      state_fio->Fwrite(seek_step_id, sizeof(seek_step_id), 1);
1940 //      state_fio->Fwrite(seek_end_id, sizeof(seek_end_id), 1);
1941 //      state_fio->Fwrite(head_unload_id, sizeof(head_unload_id), 1);
1942 //      state_fio->FputBool(force_ready);
1943 //      state_fio->FputBool(reset_signal);
1944 //      state_fio->FputBool(prev_index);
1945 //      state_fio->FputUint32(prev_drq_clock);
1946 }
1947
1948 bool UPD765A::load_state(FILEIO* state_fio)
1949 {
1950         bool mb = false;
1951         if(state_entry != NULL) {
1952                 mb = state_entry->load_state(state_fio);
1953         }
1954         if(!mb) return false;
1955
1956 //      if(state_fio->FgetUint32() != STATE_VERSION) {
1957 //              return false;
1958 //      }
1959 //      if(state_fio->FgetInt32() != this_device_id) {
1960 //              return false;
1961 //      }
1962 //      state_fio->Fread(fdc, sizeof(fdc), 1);
1963         for(int i = 0; i < 4; i++) {
1964                 if(!disk[i]->load_state(state_fio)) {
1965                         return false;
1966                 }
1967         }
1968 //      hdu = state_fio->FgetUint8();
1969 //      hdue = state_fio->FgetUint8();
1970 //      state_fio->Fread(id, sizeof(id), 1);
1971 //      eot = state_fio->FgetUint8();
1972 //      gpl = state_fio->FgetUint8();
1973 //      dtl = state_fio->FgetUint8();
1974 //      phase = state_fio->FgetInt32();
1975 //      prevphase = state_fio->FgetInt32();
1976 //      status = state_fio->FgetUint8();
1977 //      seekstat = state_fio->FgetUint8();
1978 //      command = state_fio->FgetUint8();
1979 //      result = state_fio->FgetUint32();
1980 //      step_rate_time = state_fio->FgetInt32();
1981 //      head_unload_time = state_fio->FgetInt32();
1982 //      no_dma_mode = state_fio->FgetBool();
1983 //      motor_on = state_fio->FgetBool();
1984 //#ifdef UPD765A_DMA_MODE
1985 //      if(_upd765a_dma_mode) dma_data_lost = state_fio->FgetBool();
1986 //#endif
1987 //      irq_masked = state_fio->FgetBool();
1988 //      drq_masked = state_fio->FgetBool();
1989 //      bufptr = buffer + state_fio->FgetInt32();
1990 //      state_fio->Fread(buffer, sizeof(buffer), 1);
1991 //      count = state_fio->FgetInt32();
1992 //      event_phase = state_fio->FgetInt32();
1993 //      phase_id = state_fio->FgetInt32();
1994 //      drq_id = state_fio->FgetInt32();
1995 //      lost_id = state_fio->FgetInt32();
1996 //      result7_id = state_fio->FgetInt32();
1997 //      state_fio->Fread(seek_step_id, sizeof(seek_step_id), 1);
1998 //      state_fio->Fread(seek_end_id, sizeof(seek_end_id), 1);
1999 //      state_fio->Fread(head_unload_id, sizeof(head_unload_id), 1);
2000 //      force_ready = state_fio->FgetBool();
2001 //      reset_signal = state_fio->FgetBool();
2002 //      prev_index = state_fio->FgetBool();
2003 //      prev_drq_clock = state_fio->FgetUint32();
2004
2005         if(tmp_bufsize < 0) tmp_bufsize = 0;
2006         if(tmp_bufsize > sizeof(buffer)) tmp_bufsize = sizeof(buffer);
2007         bufptr = buffer + tmp_bufsize;
2008         
2009         _fdc_debug_log = config.special_debug_fdc;
2010         return true;
2011 }
2012