2 Skelton for retropc emulator
5 Author : Takeda.Toshiya
18 #define EVENT_RESULT7 3
20 #define EVENT_SEEK_STEP 5 // 5-8
21 #define EVENT_SEEK_END 9 // 9-12
22 #define EVENT_UNLOAD 13 // 13-16
32 #define PHASE_RESULT 8
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
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
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
74 #define REGISTER_PHASE_EVENT(phs, usec) { \
75 if(phase_id != -1) { \
76 cancel_event(this, phase_id); \
79 register_event(this, EVENT_PHASE, 100, false, &phase_id); \
82 #define REGISTER_PHASE_EVENT_NEW(phs, usec) { \
83 if(phase_id != -1) { \
84 cancel_event(this, phase_id); \
87 register_event(this, EVENT_PHASE, usec, false, &phase_id); \
90 #define REGISTER_DRQ_EVENT() { \
91 double usec = disk[hdu & DRIVE_MASK]->get_usec_per_bytes(1) - get_passed_usec(prev_drq_clock); \
95 register_event(this, EVENT_DRQ, usec, false, &drq_id); \
98 #define CANCEL_EVENT() { \
99 if(phase_id != -1) { \
100 cancel_event(this, phase_id); \
104 cancel_event(this, drq_id); \
107 if(lost_id != -1) { \
108 cancel_event(this, lost_id); \
111 if(result7_id != -1) { \
112 cancel_event(this, result7_id); \
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; \
120 if(seek_end_id[d] != -1) { \
121 cancel_event(this, seek_end_id[d]); \
122 seek_end_id[d] = -1; \
124 if(head_unload_id[d] != -1) { \
125 cancel_event(this, head_unload_id[d]); \
126 head_unload_id[d] = -1; \
131 void UPD765A::initialize()
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;
140 //_fdc_debug_log = osd->check_feature(_T("_FDC_DEBUG_LOG"));
141 _fdc_debug_log = config.special_debug_fdc;
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"));
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);
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"));
165 d_noise_seek->set_mute(!config.sound_noise_fdd);
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);
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);
179 memset(fdc, 0, sizeof(fdc));
180 memset(buffer, 0, sizeof(buffer));
182 phase = prevphase = PHASE_IDLE;
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;
190 step_rate_time = head_unload_time = 0;
192 motor_on = false; // motor off
194 irq_masked = drq_masked = false;
195 //#ifdef UPD765A_DMA_MODE
196 dma_data_lost = false;
201 //#ifdef UPD765A_EXT_DRVSEL
202 if(_upd765a_ext_drvsel) {
211 if(outputs_index.count) {
212 register_event(this, EVENT_INDEX, 4, true, NULL);
217 void UPD765A::release()
219 for(int i = 0; i < 4; i++) {
227 void UPD765A::reset()
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]);
237 seek_step_id[i] = seek_end_id[i] = head_unload_id[i] = -1;
243 static const char* get_command_name(uint8_t data)
245 static char name[16];
247 switch(data & 0x1f) {
249 my_sprintf_s(name, 16, _T("RD DIAGNOSTIC"));
252 my_sprintf_s(name, 16, _T("SPECIFY "));
255 my_sprintf_s(name, 16, _T("SENCE DEVSTAT"));
259 my_sprintf_s(name, 16, _T("WRITE DATA "));
263 my_sprintf_s(name, 16, _T("READ DATA "));
266 my_sprintf_s(name, 16, _T("RECALIB "));
269 my_sprintf_s(name, 16, _T("SENCE INTSTAT"));
272 my_sprintf_s(name, 16, _T("READ ID "));
275 my_sprintf_s(name, 16, _T("WRITE ID "));
278 my_sprintf_s(name, 16, _T("SEEK "));
283 my_sprintf_s(name, 16, _T("SCAN "));
286 my_sprintf_s(name, 16, _T("INVALID "));
292 void UPD765A::write_io8(uint32_t addr, uint32_t data)
296 if((status & (S_RQM | S_DIO)) == S_RQM) {
301 //#ifdef _FDC_DEBUG_LOG
303 this->out_debug_log(_T("FDC: CMD=%2x %s\n"), data, get_command_name(data));
307 process_cmd(command & 0x1f);
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()
317 process_cmd(command & 0x1f);
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()
328 REGISTER_DRQ_EVENT();
330 process_cmd(command & 0x1f);
332 fdc[hdu & DRIVE_MASK].access = true;
337 if(((command & 0x1f) == 0x11 && *bufptr != data) ||
338 ((command & 0x1f) == 0x19 && *bufptr > data) ||
339 ((command & 0x1f) == 0x1d && *bufptr < data)) {
346 REGISTER_DRQ_EVENT();
350 fdc[hdu & DRIVE_MASK].access = true;
357 uint32_t UPD765A::read_io8(uint32_t addr)
361 if((status & (S_RQM | S_DIO)) == (S_RQM | S_DIO)) {
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()
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++) {
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()
398 REGISTER_DRQ_EVENT();
400 process_cmd(command & 0x1f);
402 fdc[hdu & DRIVE_MASK].access = true;
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);
413 process_cmd(command & 0x1f);
416 //#ifdef _FDC_DEBUG_LOG
417 // if(_fdc_debug_log) this->out_debug_log(_T("FDC: STATUS=%2x\n"), seekstat | status);
419 return seekstat | status;
423 void UPD765A::write_dma_io8(uint32_t addr, uint32_t data)
425 //#ifdef UPD765A_DMA_MODE
426 // EPSON QC-10 CP/M Plus
427 if(_upd765a_dma_mode) dma_data_lost = false;
432 uint32_t UPD765A::read_dma_io8(uint32_t addr)
434 //#ifdef UPD765A_DMA_MODE
435 // EPSON QC-10 CP/M Plus
436 if(_upd765a_dma_mode) dma_data_lost = false;
441 void UPD765A::write_signal(int id, uint32_t data, uint32_t mask)
443 if(id == SIG_UPD765A_RESET) {
444 bool next = ((data & mask) != 0);
445 if(!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)) {
454 process_cmd(command & 0x1f);
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);
468 } else if(id == SIG_UPD765A_IRQ_MASK) {
469 if(!(irq_masked = ((data & mask) != 0))) {
470 write_signals(&outputs_irq, 0);
472 } else if(id == SIG_UPD765A_DRQ_MASK) {
473 if(!(drq_masked = ((data & mask) != 0))) {
474 write_signals(&outputs_drq, 0);
476 } else if(id == SIG_UPD765A_FREADY) {
477 // for NEC PC-98x1 series
478 force_ready = ((data & mask) != 0);
482 uint32_t UPD765A::read_signal(int ch)
486 for(int i = 0; i < 4; i++) {
490 fdc[i].access = false;
495 void UPD765A::event_callback(int event_id, int err)
497 if(event_id == EVENT_PHASE) {
500 process_cmd(command & 0x1f);
501 } else if(event_id == EVENT_DRQ) {
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();
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"));
517 } else if(event_id == EVENT_RESULT7) {
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;
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();
537 if(fdc[drv].cur_track == fdc[drv].track) {
538 cancel_event(this, seek_step_id[drv]);
539 seek_step_id[drv] = -1;
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) {
545 cancel_event(this, seek_step_id[drv]);
546 seek_step_id[drv] = -1;
548 seek_end_id[drv] = -1;
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;
556 head_unload_id[drv] = -1;
560 void UPD765A::set_irq(bool val)
562 //#ifdef _FDC_DEBUG_LOG
563 // if(_fdc_debug_log) this->out_debug_log(_T("FDC: IRQ=%d\n"), val ? 1 : 0);
565 write_signals(&outputs_irq, (val && !irq_masked) ? 0xffffffff : 0);
568 void UPD765A::set_drq(bool val)
570 //#ifdef _FDC_DEBUG_LOG
571 // if(_fdc_debug_log) this->out_debug_log(_T("FDC: DRQ=%d\n"), val ? 1 : 0);
573 // cancel next drq and data lost events
575 cancel_event(this, drq_id);
578 cancel_event(this, lost_id);
580 drq_id = lost_id = -1;
581 // register data lost event if data exists
583 //#ifdef UPD765A_DMA_MODE
584 // EPSON QC-10 CP/M Plus
585 if(_upd765a_dma_mode) {
586 dma_data_lost = true;
589 if((command & 0x1f) != 0x0d) {
590 register_event(this, EVENT_LOST, disk[hdu & DRIVE_MASK]->get_usec_per_bytes(1), false, &lost_id);
593 register_event(this, EVENT_LOST, 30000, false, &lost_id);
599 write_signals(&outputs_irq, (val && !irq_masked) ? 0xffffffff : 0);
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"));
610 write_signals(&outputs_drq, 0);
618 void UPD765A::set_hdu(uint8_t val)
620 //#ifdef UPD765A_EXT_DRVSEL
621 if(_upd765a_ext_drvsel) {
622 hdu = (hdu & 3) | (val & 4);
628 write_signals(&outputs_hdu, hdu);
631 // ----------------------------------------------------------------------------
633 // ----------------------------------------------------------------------------
635 void UPD765A::process_cmd(int cmd)
639 cmd_read_diagnostic();
681 void UPD765A::cmd_sence_devstat()
689 buffer[0] = get_devstat(buffer[0] & DRIVE_MASK);
695 void UPD765A::cmd_sence_intstat()
697 for(int i = 0; i < 4; i++) {
699 buffer[0] = (uint8_t)fdc[i].result;
700 buffer[1] = (uint8_t)fdc[i].track;
706 //#ifdef UPD765A_SENCE_INTSTAT_RESULT
708 if(_upd765a_sence_intstat_result) {
709 buffer[0] = (uint8_t)ST0_AI;
712 buffer[0] = (uint8_t)ST0_IC;
719 uint8_t UPD765A::get_devstat(int drv)
721 if(drv >= _max_drive) {
725 if(force_ready && !disk[drv]->inserted) {
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);
731 void UPD765A::cmd_seek()
738 seek(buffer[0] & DRIVE_MASK, buffer[1]);
744 void UPD765A::cmd_recalib()
751 seek(buffer[0] & DRIVE_MASK, 0);
757 void UPD765A::seek(int drv, int trk)
760 int steptime = (32 - 2 * step_rate_time) * 1000; // msec -> usec
761 if(disk[drv]->drive_type == DRIVE_TYPE_2HD) {
764 int seektime = (trk == fdc[drv].track) ? 120 : steptime * abs(trk - fdc[drv].track) + 500; // usec
766 if(drv >= _max_drive) {
767 // invalid drive number
768 fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR | ST0_AT;
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();
781 if(seek_step_id[drv] != -1) {
782 cancel_event(this, seek_step_id[drv]);
784 if(seek_end_id[drv] != -1) {
785 cancel_event(this, seek_end_id[drv]);
787 if(fdc[drv].cur_track != fdc[drv].track) {
788 register_event(this, EVENT_SEEK_STEP + drv, steptime, true, &seek_step_id[drv]);
790 seek_step_id[drv] = -1;
792 register_event(this, EVENT_SEEK_END + drv, seektime, false, &seek_end_id[drv]);
793 seekstat |= 1 << drv;
799 void UPD765A::seek_event(int drv)
801 int trk = fdc[drv].track;
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;
808 //#ifdef UPD765A_NO_ST0_AT_FOR_SEEK
809 if(_upd765a_no_st0_at_for_seek) {
811 fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR;
814 fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR | ST0_AT;
819 seekstat &= ~(1 << drv);
822 disk[drv]->changed = false;
825 void UPD765A::cmd_read_data()
834 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
838 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
839 REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
842 read_data((command & 0x1f) == 12, false);
850 REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
853 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
860 // result = ST0_AT | ST1_EN;
867 void UPD765A::cmd_write_data()
876 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
880 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
881 REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
884 result = check_cond(true);
885 if(result & ST1_MA) {
886 REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000); // retry
895 int length = 0x80 << (id[3] & 7);
897 length = min(dtl, 0x80);
898 memset(buffer + length, 0, 0x80 - length);
900 shift_to_write(length);
904 write_data((command & 0x1f) == 9);
911 REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
914 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
917 // result = ST0_AT | ST1_EN;
923 if(prevphase == PHASE_WRITE && bufptr != buffer) {
924 // terminate while transfer ?
925 memset(bufptr, 0, count);
926 write_data((command & 0x1f) == 9);
933 void UPD765A::cmd_scan()
943 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
947 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
948 REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
951 read_data(false, true);
960 REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
963 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
970 // result = ST0_AT | ST1_EN;
977 void UPD765A::cmd_read_diagnostic()
986 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
990 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
991 REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
997 if(result & ~ST1_ND) {
1002 REGISTER_PHASE_EVENT(PHASE_TIMER, 2000);
1005 REGISTER_PHASE_EVENT_NEW(PHASE_EXEC, get_usec_to_exec_phase());
1012 // result |= ST0_AT | ST1_EN;
1019 void UPD765A::read_data(bool deleted, bool scan)
1021 result = check_cond(false);
1022 if(result & ST1_MA) {
1023 REGISTER_PHASE_EVENT(PHASE_EXEC, 10000);
1030 result = read_sector();
1034 if((result & ~ST2_CM) && !(result & ST2_DD)) {
1038 if((result & ST2_CM) && (command & 0x20)) {
1039 REGISTER_PHASE_EVENT(PHASE_TIMER, 100000);
1042 int length = (id[3] & 7) ? (0x80 << (id[3] & 7)) : (min(dtl, 0x80));
1044 shift_to_read(length);
1046 shift_to_scan(length);
1051 void UPD765A::write_data(bool deleted)
1053 if((result = check_cond(true)) != 0) {
1057 result = write_sector(deleted);
1061 void UPD765A::read_diagnostic()
1063 int drv = hdu & DRIVE_MASK;
1064 int trk = fdc[drv].track;
1065 int side = (hdu >> 2) & 1;
1067 result = check_cond(false);
1068 if(result & ST1_MA) {
1069 REGISTER_PHASE_EVENT(PHASE_EXEC, 10000);
1076 if(!disk[drv]->make_track(trk, side)) {
1078 result = ST0_AT | ST1_MA;
1082 if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1084 result = ST0_AT | ST1_MA;
1088 if(disk[drv]->get_sector(trk, side, 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]*/) {
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]) {
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];
1104 shift_to_read(0x80 << (id[3] & 7));
1108 uint32_t UPD765A::read_sector()
1110 int drv = hdu & DRIVE_MASK;
1111 int trk = fdc[drv].track;
1112 int side = (hdu >> 2) & 1;
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);
1119 return ST0_AT | ST1_MA;
1121 if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1122 return ST0_AT | ST1_MA;
1124 int secnum = disk[drv]->sector_num.sd;
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);
1129 return ST0_AT | ST1_MA;
1132 for(int i = 0; i < secnum; i++) {
1133 if(!disk[drv]->get_sector(trk, side, i)) {
1136 cy = disk[drv]->id[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]*/) {
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]) {
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]);
1147 if(disk[drv]->sector_size.sd == 0) {
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);
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]);
1158 fdc[drv].next_trans_position = disk[drv]->data_position[i];
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);
1163 if(disk[drv]->deleted) {
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]);
1171 if(cy != id[0] && cy != -1) {
1173 return ST0_AT | ST1_ND | ST2_BC;
1175 return ST0_AT | ST1_ND | ST2_NC;
1178 return ST0_AT | ST1_ND;
1181 uint32_t UPD765A::write_sector(bool deleted)
1183 int drv = hdu & DRIVE_MASK;
1184 int trk = fdc[drv].track;
1185 int side = (hdu >> 2) & 1;
1187 if(disk[drv]->write_protected) {
1188 return ST0_AT | ST1_NW;
1190 // get sector counts in the current track
1191 if(!disk[drv]->get_track(trk, side)) {
1192 return ST0_AT | ST1_MA;
1194 int secnum = disk[drv]->sector_num.sd;
1196 return ST0_AT | ST1_MA;
1199 for(int i = 0; i < secnum; i++) {
1200 if(!disk[drv]->get_sector(trk, side, i)) {
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]*/) {
1207 if(disk[drv]->sector_size.sd == 0) {
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);
1216 if(cy != id[0] && cy != -1) {
1218 return ST0_AT | ST1_ND | ST2_BC;
1220 return ST0_AT | ST1_ND | ST2_NC;
1223 return ST0_AT | ST1_ND;
1226 uint32_t UPD765A::find_id()
1228 int drv = hdu & DRIVE_MASK;
1229 int trk = fdc[drv].track;
1230 int side = (hdu >> 2) & 1;
1232 // get sector counts in the current track
1233 if(!disk[drv]->get_track(trk, side)) {
1234 return ST0_AT | ST1_MA;
1236 if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1237 return ST0_AT | ST1_MA;
1239 int secnum = disk[drv]->sector_num.sd;
1241 return ST0_AT | ST1_MA;
1244 for(int i = 0; i < secnum; i++) {
1245 if(!disk[drv]->get_sector(trk, side, i)) {
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]*/) {
1252 if(disk[drv]->sector_size.sd == 0) {
1255 // sector number is matched
1256 fdc[drv].next_trans_position = disk[drv]->data_position[i];
1259 if(cy != id[0] && cy != -1) {
1261 return ST0_AT | ST1_ND | ST2_BC;
1263 return ST0_AT | ST1_ND | ST2_NC;
1266 return ST0_AT | ST1_ND;
1269 uint32_t UPD765A::check_cond(bool write)
1271 int drv = hdu & DRIVE_MASK;
1273 if(drv >= _max_drive) {
1274 return ST0_AT | ST0_NR;
1276 if(!disk[drv]->inserted) {
1277 return ST0_AT | ST1_MA;
1282 void UPD765A::get_sector_params()
1295 bool UPD765A::id_incr()
1297 if((command & 19) == 17) {
1299 if((dtl & 0xff) == 0x02) {
1303 if(id[2]++ != eot) {
1307 if(command & 0x80) {
1318 void UPD765A::cmd_read_id()
1330 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
1331 REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
1334 if(check_cond(false) & ST1_MA) {
1335 // REGISTER_PHASE_EVENT(PHASE_EXEC, 1000000);
1338 if((result = read_id()) == 0) {
1339 int drv = hdu & DRIVE_MASK;
1340 int bytes = fdc[drv].next_trans_position - get_cur_position(drv);
1342 bytes += disk[drv]->get_track_size();
1344 REGISTER_PHASE_EVENT_NEW(PHASE_TIMER, disk[drv]->get_usec_per_bytes(bytes));
1346 REGISTER_PHASE_EVENT(PHASE_TIMER, 5000);
1355 void UPD765A::cmd_write_id()
1366 dtl = buffer[4]; // temporary
1368 REGISTER_PHASE_EVENT(PHASE_TIMER, 1000000);
1372 fdc[hdu & DRIVE_MASK].next_trans_position = get_cur_position(hdu & DRIVE_MASK);
1373 shift_to_write(4 * eot);
1377 REGISTER_PHASE_EVENT(PHASE_TIMER, 4000000);
1381 if(force_ready && !disk[hdu & DRIVE_MASK]->inserted) {
1382 REGISTER_PHASE_EVENT(PHASE_TIMER, 1000000);
1385 result = write_id();
1391 uint32_t UPD765A::read_id()
1393 int drv = hdu & DRIVE_MASK;
1394 int trk = fdc[drv].track;
1395 int side = (hdu >> 2) & 1;
1397 // get sector counts in the current track
1398 if(!disk[drv]->get_track(trk, side)) {
1399 return ST0_AT | ST1_MA;
1401 if((command & 0x40) != (disk[drv]->track_mfm ? 0x40 : 0)) {
1402 return ST0_AT | ST1_MA;
1404 int secnum = disk[drv]->sector_num.sd;
1406 return ST0_AT | ST1_MA;
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();
1414 for(int i = 0; i < secnum; i++) {
1415 if(position < disk[drv]->sync_position[i]) {
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;
1431 return ST0_AT | ST1_ND;
1434 uint32_t UPD765A::write_id()
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);
1441 if((result = check_cond(true)) != 0) {
1444 if(disk[drv]->write_protected) {
1445 return ST0_AT | ST1_NW;
1448 disk[drv]->format_track(trk, side);
1449 disk[drv]->track_mfm = ((command & 0x40) != 0);
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];
1455 disk[drv]->insert_sector(id[0], id[1], id[2], id[3], false, false, dtl, length);
1460 void UPD765A::cmd_specify()
1467 step_rate_time = buffer[0] >> 4;
1468 head_unload_time = buffer[1] >> 1;
1469 no_dma_mode = ((buffer[1] & 1) != 0);
1471 status = 0x80;//0xff;
1476 void UPD765A::cmd_invalid()
1478 buffer[0] = (uint8_t)ST0_IC;
1482 void UPD765A::shift_to_idle()
1488 void UPD765A::shift_to_cmd(int length)
1491 status = S_RQM | S_CB;
1496 void UPD765A::shift_to_exec()
1499 process_cmd(command & 0x1f);
1502 void UPD765A::shift_to_read(int length)
1505 status = S_RQM | S_DIO | S_NDM | S_CB;
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();
1515 void UPD765A::shift_to_write(int length)
1517 phase = PHASE_WRITE;
1518 status = S_RQM | S_NDM | S_CB;
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();
1528 void UPD765A::shift_to_scan(int length)
1531 status = S_RQM | S_NDM | S_CB;
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();
1542 void UPD765A::shift_to_result(int length)
1544 phase = PHASE_RESULT;
1545 status = S_RQM | S_CB | S_DIO;
1550 void UPD765A::shift_to_result7()
1552 //#ifdef UPD765A_WAIT_RESULT7
1553 if(_upd765a_wait_result7) {
1554 if(result7_id != -1) {
1555 cancel_event(this, result7_id);
1558 if(phase != PHASE_TIMER) {
1559 register_event(this, EVENT_RESULT7, 100, false, &result7_id);
1562 shift_to_result7_event();
1565 shift_to_result7_event();
1570 void UPD765A::shift_to_result7_event()
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);
1576 buffer[0] = (result & 0xf8) | (hdue & 7);
1577 buffer[1] = uint8_t(result >> 8);
1578 buffer[2] = uint8_t(result >> 16);
1587 void UPD765A::start_transfer()
1589 int drv = hdu & DRIVE_MASK;
1591 if(head_unload_id[drv] != -1) {
1592 cancel_event(this, head_unload_id[drv]);
1593 head_unload_id[drv] = -1;
1595 if(!fdc[drv].head_load) {
1596 if(d_noise_head_down != NULL) d_noise_head_down->play();
1597 fdc[drv].head_load = true;
1601 void UPD765A::finish_transfer()
1603 int drv = hdu & DRIVE_MASK;
1605 if(fdc[drv].head_load) {
1606 if(head_unload_id[drv] != -1) {
1607 cancel_event(this, head_unload_id[drv]);
1609 int time = (16 * (head_unload_time + 1)) * 1000; // msec -> usec
1610 if(disk[drv]->drive_type == DRIVE_TYPE_2HD) {
1613 register_event(this, EVENT_UNLOAD + drv, time, false, &head_unload_id[drv]);
1617 // ----------------------------------------------------------------------------
1619 // ----------------------------------------------------------------------------
1621 int UPD765A::get_cur_position(int drv)
1623 return (fdc[drv].cur_position + disk[drv]->get_bytes_per_usec(get_passed_usec(fdc[drv].prev_clock))) % disk[drv]->get_track_size();
1626 double UPD765A::get_usec_to_exec_phase()
1628 int drv = hdu & DRIVE_MASK;
1629 int trk = fdc[drv].track;
1630 int side = (hdu >> 2) & 1;
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
1638 // search target sector
1639 int position = get_cur_position(drv);
1640 int trans_position = -1, sync_position;
1642 if(disk[drv]->get_track(trk, side) && disk[drv]->sector_num.sd != 0) {
1643 if((command & 0x1f) == 0x02) {
1645 trans_position = disk[drv]->data_position[0];
1646 sync_position = disk[drv]->sync_position[0];
1648 for(int i = 0; i < disk[drv]->sector_num.sd; i++) {
1649 if(!disk[drv]->get_sector(trk, side, i)) {
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]*/) {
1655 // sector number is matched
1656 trans_position = disk[drv]->data_position[i];
1657 sync_position = disk[drv]->sync_position[i];
1662 if(trans_position == -1) {
1667 // get current position
1668 int bytes = trans_position - position;
1669 if(sync_position < position) {
1670 bytes += disk[drv]->get_track_size();
1672 return disk[drv]->get_usec_per_bytes(bytes);
1675 // ----------------------------------------------------------------------------
1677 // ----------------------------------------------------------------------------
1679 void UPD765A::open_disk(int drv, const _TCHAR* file_path, int bank)
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);
1687 if(raise_irq_when_media_changed) {
1688 fdc[drv].result = (drv & DRIVE_MASK) | ST0_AI | ST0_NR;
1695 void UPD765A::close_disk(int drv)
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;
1703 //#ifdef _FDC_DEBUG_LOG
1704 if(_fdc_debug_log) this->out_debug_log(_T("FDC: Disk Ejected (Drive=%d)\n"), drv);
1706 if(raise_irq_when_media_changed) {
1707 fdc[drv].result = (drv & DRIVE_MASK) | ST0_AI;
1713 bool UPD765A::is_disk_inserted(int drv)
1715 if(drv < _max_drive) {
1716 return disk[drv]->inserted;
1721 bool UPD765A::is_disk_inserted()
1723 int drv = hdu & DRIVE_MASK;
1724 return is_disk_inserted(drv);
1727 bool UPD765A::disk_ejected(int drv)
1729 if(drv < _max_drive) {
1730 return disk[drv]->ejected;
1735 bool UPD765A::disk_ejected()
1737 int drv = hdu & DRIVE_MASK;
1738 return disk_ejected(drv);
1741 void UPD765A::is_disk_protected(int drv, bool value)
1743 if(drv < _max_drive) {
1744 disk[drv]->write_protected = value;
1748 bool UPD765A::is_disk_protected(int drv)
1750 if(drv < _max_drive) {
1751 return disk[drv]->write_protected;
1756 uint8_t UPD765A::get_media_type(int drv)
1758 if(drv < _max_drive && disk[drv]->inserted) {
1759 return disk[drv]->media_type;
1761 return MEDIA_TYPE_UNK;
1764 void UPD765A::set_drive_type(int drv, uint8_t type)
1766 if(drv < _max_drive) {
1767 disk[drv]->drive_type = type;
1771 uint8_t UPD765A::get_drive_type(int drv)
1773 if(drv < _max_drive) {
1774 return disk[drv]->drive_type;
1776 return DRIVE_TYPE_UNK;
1779 void UPD765A::set_drive_rpm(int drv, int rpm)
1781 if(drv < _max_drive) {
1782 disk[drv]->drive_rpm = rpm;
1786 void UPD765A::set_drive_mfm(int drv, bool mfm)
1788 if(drv < _max_drive) {
1789 disk[drv]->drive_mfm = mfm;
1793 void UPD765A::update_config()
1795 if(d_noise_seek != NULL) {
1796 d_noise_seek->set_mute(!config.sound_noise_fdd);
1798 if(d_noise_head_down != NULL) {
1799 d_noise_head_down->set_mute(!config.sound_noise_fdd);
1801 if(d_noise_head_up != NULL) {
1802 d_noise_head_up->set_mute(!config.sound_noise_fdd);
1804 _fdc_debug_log = config.special_debug_fdc;
1807 //#ifdef USE_DEBUGGER
1808 void UPD765A::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
1810 int drv = hdu & DRIVE_MASK;
1811 int side = (hdu >> 2) & 1;
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);
1822 #define STATE_VERSION 3
1824 #include "../statesub.h"
1826 void UPD765A::decl_state_fdc(int ch)
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);
1832 DECL_STATE_ENTRY_BOOL_MEMBER((fdc[ch].access), ch);
1833 DECL_STATE_ENTRY_BOOL_MEMBER((fdc[ch].head_load), ch);
1835 DECL_STATE_ENTRY_INT32_MEMBER((fdc[ch].cur_position), ch);
1836 DECL_STATE_ENTRY_INT32_MEMBER((fdc[ch].next_trans_position), ch);
1838 DECL_STATE_ENTRY_UINT32_MEMBER((fdc[ch].prev_clock), ch);
1842 void UPD765A::decl_state()
1844 enter_decl_state(STATE_VERSION);
1846 for(int i = 0; i < 4; i++) {
1850 DECL_STATE_ENTRY_UINT8(hdu);
1851 DECL_STATE_ENTRY_UINT8(hdue);
1852 DECL_STATE_ENTRY_1D_ARRAY(id, sizeof(id));
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);
1870 DECL_STATE_ENTRY_BOOL(irq_masked);
1871 DECL_STATE_ENTRY_BOOL(drq_masked);
1873 DECL_STATE_ENTRY_INT32(tmp_bufsize);
1874 DECL_STATE_ENTRY_1D_ARRAY(buffer, sizeof(buffer));
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);
1890 for(int i = 0; i < 4; i++) {
1891 disk[i]->decl_state(p_logger);
1895 void UPD765A::save_state(FILEIO* state_fio)
1897 tmp_bufsize = (int)(bufptr - buffer);
1899 if(state_entry != NULL) {
1900 state_entry->save_state(state_fio);
1903 // state_fio->FputUint32(STATE_VERSION);
1904 // state_fio->FputInt32(this_device_id);
1906 // state_fio->Fwrite(fdc, sizeof(fdc), 1);
1907 for(int i = 0; i < 4; i++) {
1908 disk[i]->save_state(state_fio);
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);
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);
1948 bool UPD765A::load_state(FILEIO* state_fio)
1951 if(state_entry != NULL) {
1952 mb = state_entry->load_state(state_fio);
1954 if(!mb) return false;
1956 // if(state_fio->FgetUint32() != STATE_VERSION) {
1959 // if(state_fio->FgetInt32() != this_device_id) {
1962 // state_fio->Fread(fdc, sizeof(fdc), 1);
1963 for(int i = 0; i < 4; i++) {
1964 if(!disk[i]->load_state(state_fio)) {
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();
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();
2005 if(tmp_bufsize < 0) tmp_bufsize = 0;
2006 if(tmp_bufsize > sizeof(buffer)) tmp_bufsize = sizeof(buffer);
2007 bufptr = buffer + tmp_bufsize;
2009 _fdc_debug_log = config.special_debug_fdc;