OSDN Git Service

[VM][FM8][FM77] Add delay FIRQ/NMI from 2HD/SFD FDC.This is temporally implement.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mb8877.cpp
index a21d553..d186b5c 100644 (file)
 #define FDC_CMD_RD_TRK         7
 #define FDC_CMD_WR_TRK         8
 
-#define EVENT_SEEK             0
-#define EVENT_SEEKEND          1
-#define EVENT_SEARCH           2
-#define EVENT_DRQ              3
-#define EVENT_MULTI1           4
-#define EVENT_MULTI2           5
-#define EVENT_LOST             6
+#define EVENT_SEEK                             0
+#define EVENT_SEEKEND_VERIFY   1
+#define EVENT_SEARCH                   2
+#define EVENT_DRQ                              3
+#define EVENT_MULTI1                   4
+#define EVENT_MULTI2                   5
+#define EVENT_LOST                             6
 
 //#define DRIVE_MASK           (MAX_DRIVE - 1)
 
@@ -79,18 +79,20 @@ void MB8877::register_seek_event()
 
 void MB8877::register_drq_event(int bytes)
 {
-       double usec = disk[drvreg]->get_usec_per_bytes(bytes) - get_passed_usec(prev_drq_clock);
+       double nusec = disk[drvreg]->get_usec_per_bytes(bytes); // For debug
+       double usec = nusec - get_passed_usec(prev_drq_clock);
+
        if(usec < 4) {
                usec = 4;
        }
-//#if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
        if(type_fm7) {
                if((disk[drvreg]->is_special_disk == SPECIAL_DISK_FM7_GAMBLER) ||
-                  (disk[drvreg]->is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE)) {
-                       usec = 4;
+                  /* (disk[drvreg]->is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE) || */
+                  (config.correct_disk_timing[drvreg])) {
+                       usec = 7;
                }
        }
-//#endif
+       this->out_debug_log("DRQ REG: %dbytes %d:%d -> %f\n", bytes, get_current_clock(), prev_drq_clock, usec);
        cancel_my_event(EVENT_DRQ);
        register_event(this, (EVENT_DRQ << 8) | (cmdtype & 0xff), usec, false, &register_id[EVENT_DRQ]);
 }
@@ -101,11 +103,42 @@ void MB8877::register_lost_event(int bytes)
        register_event(this, (EVENT_LOST << 8) | (cmdtype & 0xff), disk[drvreg]->get_usec_per_bytes(bytes), false, &register_id[EVENT_LOST]);
 }
 
+bool MB8877::check_drive(void)
+{
+       if(drvreg >= _max_drive) {
+               status = FDC_ST_NOTREADY;
+               //set_drq(false);
+               set_irq(true);
+               return false;
+       }
+       return true;
+}
+
+bool MB8877::check_drive2(void)
+{
+       if(!check_drive()) {
+               return false;
+       }
+       if(!is_disk_inserted(drvreg & 0x7f)) {
+               status = FDC_ST_NOTREADY;
+               set_irq(true);
+               //set_drq(false);
+               return false;
+       }
+       return true;
+}
+
 void MB8877::initialize()
 {
        DEVICE::initialize();
        // initialize d88 handler
-       _max_drive = osd->get_feature_int_value(_T("MAX_DRIVE"));
+       if(osd->check_feature(_T("MAX_DRIVE"))) {
+               _max_drive = osd->get_feature_int_value(_T("MAX_DRIVE"));
+       } else if(osd->check_feature(_T("MAX_FD"))) {
+               _max_drive = osd->get_feature_int_value(_T("MAX_FD"));
+       } else {
+               _max_drive = 1;
+       }
        _drive_mask = _max_drive - 1;
        for(int i = 0; i < _max_drive; i++) {
                disk[i] = new DISK(emu);
@@ -175,7 +208,10 @@ void MB8877::initialize()
        
        // initialize timing
        memset(fdc, 0, sizeof(fdc));
-       
+       for(int i = 0; i < 16; i++) {
+               fdc[i].track = 40;  // OK?
+               fdc[i].count_immediate = false;
+       }
        // initialize fdc
        seektrk = 0;
        seekvct = true;
@@ -198,7 +234,7 @@ void MB8877::release()
 void MB8877::reset()
 {
        for(int i = 0; i < _max_drive; i++) {
-               fdc[i].track = 0;
+               //fdc[i].track = 0; // Hold to track
                fdc[i].index = 0;
                fdc[i].access = false;
        }
@@ -336,6 +372,7 @@ void MB8877::write_io8(uint32_t addr, uint32_t data)
                                        } else {
                                                register_drq_event(1);
                                        }
+                                       if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
                                }
                                status &= ~FDC_ST_DRQ;
                        } else if(cmdtype == FDC_CMD_WR_TRK) {
@@ -425,6 +462,7 @@ write_id:
                                        } else {
                                                register_drq_event(1);
                                        }
+                                       if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
                                }
                                status &= ~FDC_ST_DRQ;
                        }
@@ -578,9 +616,8 @@ uint32_t MB8877::read_io8(uint32_t addr)
                                // read or multisector read
                                if(fdc[drvreg].index < disk[drvreg]->sector_size.sd) {
                                        datareg = disk[drvreg]->sector[fdc[drvreg].index];
-                                       //fdc[drvreg].index++;
                                }
-                               if((fdc[drvreg].index + 1) >= disk[drvreg]->sector_size.sd) {
+                               if((fdc[drvreg].index + 1) >= disk[drvreg]->sector_size.sd) {  // Reading complete this sector.
 
                                        if(disk[drvreg]->data_crc_error && !disk[drvreg]->ignore_crc()) {
                                                // data crc error
@@ -607,8 +644,9 @@ uint32_t MB8877::read_io8(uint32_t addr)
                                                register_my_event(EVENT_MULTI1, 30);
                                                register_my_event(EVENT_MULTI2, 60);
                                        }
-                               } else {
+                               } else { // Still data remain.
                                        register_drq_event(1);
+                                       if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
                                }
                                status &= ~FDC_ST_DRQ;
                        } else if(cmdtype == FDC_CMD_RD_ADDR) {
@@ -630,6 +668,7 @@ uint32_t MB8877::read_io8(uint32_t addr)
 //#endif
                                } else {
                                        register_drq_event(1);
+                                       if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
                                }
                                status &= ~FDC_ST_DRQ;
                        } else if(cmdtype == FDC_CMD_RD_TRK) {
@@ -648,6 +687,7 @@ uint32_t MB8877::read_io8(uint32_t addr)
                                        set_irq(true);
                                } else {
                                        register_drq_event(1);
+                                       if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
                                }
                                status &= ~FDC_ST_DRQ;
                        }
@@ -658,7 +698,7 @@ uint32_t MB8877::read_io8(uint32_t addr)
                        }
                }
 //#ifdef _FDC_DEBUG_LOG
-               if(fdc_debug_log) this->out_debug_log(_T("FDC\tDATA=%2x\n"), datareg);
+               if(fdc_debug_log) this->force_out_debug_log(_T("FDC\tDATA=%2x\n"), datareg); // emu->force_out_debug_log()
 //#endif
 //#if defined(HAS_MB8866) || defined(HAS_MB8876)
                if(invert_registers) {
@@ -692,7 +732,7 @@ void MB8877::write_signal(int id, uint32_t data, uint32_t mask)
                sidereg = (data & mask) ? 1 : 0;
        } else if(id == SIG_MB8877_MOTOR) {
                motor_on = ((data & mask) != 0);
-       }
+       } 
 }
 
 uint32_t MB8877::read_signal(int ch)
@@ -723,11 +763,12 @@ void MB8877::event_callback(int event_id, int err)
 {
        int event = event_id >> 8;
        int cmd = event_id & 0xff;
+       //bool need_after_irq = false;
        register_id[event] = -1;
        
        // cancel event if the command is finished or other command is executed
        if(cmd != cmdtype) {
-               if(event == EVENT_SEEK || event == EVENT_SEEKEND) {
+               if(event == EVENT_SEEK || event == EVENT_SEEKEND_VERIFY) {
                        now_seek = false;
                } else if(event == EVENT_SEARCH) {
                        now_search = false;
@@ -743,14 +784,20 @@ void MB8877::event_callback(int event_id, int err)
                if(seektrk > fdc[drvreg].track) {
                        fdc[drvreg].track++;
                        if(d_noise_seek != NULL) d_noise_seek->play();
+                       //need_after_irq = true;
                } else if(seektrk < fdc[drvreg].track) {
                        fdc[drvreg].track--;
                        if(d_noise_seek != NULL) d_noise_seek->play();
+                       //need_after_irq = true;
                }
                if((cmdreg & 0x10) || ((cmdreg & 0xf0) == 0)) {
                        trkreg = fdc[drvreg].track;
                }
                if(seektrk != fdc[drvreg].track) {
+                       //if(need_after_irq) {
+                               //set_drq(false);
+                               //set_irq(true);  // 20180118 K.O Turn ON IRQ -> Turn OFF DRQ
+                       //}
                        register_seek_event();
                        break;
                }
@@ -780,13 +827,22 @@ void MB8877::event_callback(int event_id, int err)
                        } else {
                                time = get_usec_to_next_trans_pos(true);
                        }
-                       register_my_event(EVENT_SEEKEND, time);
+                       // 20180128 K.O If seek completed, delay to make IRQ/DRQ at SEEKEND_VERIFY.
+                       register_my_event(EVENT_SEEKEND_VERIFY, time);
                        break;
                }
-       case EVENT_SEEKEND:
+//     case EVENT_SEEKEND: // Separate SEEK and SEEKEND when verifying. 20180128 K.O
                now_seek = false;
                status = status_tmp;
-               set_irq(true);
+               status &= (uint8_t)(~FDC_ST_BUSY);      // 20180118 K.O Turn off BUSY flag.
+               set_drq(false);
+               set_irq(true);  // 20180118 K.O Turn ON IRQ -> Turn OFF DRQ
+               break;
+       case EVENT_SEEKEND_VERIFY: // Separate SEEK and SEEKEND when verifying. 20180128 K.O
+               now_seek = false;
+               status &= (uint8_t)(~FDC_ST_BUSY);      // 20180118 K.O Turn off BUSY flag.
+               set_drq(false);
+               set_irq(true);  // 20180118 K.O Turn ON IRQ -> Turn OFF DRQ
 //#ifdef _FDC_DEBUG_LOG
                //this->out_debug_log(_T("FDC\tSEEK END\n"));
 //#endif
@@ -798,15 +854,16 @@ void MB8877::event_callback(int event_id, int err)
                        if(type_x1) {
                                // for SHARP X1 Batten Tanuki
                                if(disk[drvreg]->is_special_disk == SPECIAL_DISK_X1_BATTEN && drive_sel) {
-                               status_tmp &= ~FDC_ST_RECNFND;
-                       }
+                                       status_tmp &= ~FDC_ST_RECNFND;
+                               }
                        }
 //#endif
 //#ifdef _FDC_DEBUG_LOG
-                               if(fdc_debug_log) this->out_debug_log(_T("FDC\tSEARCH NG\n"));
+                       if(fdc_debug_log) this->out_debug_log(_T("FDC\tSEARCH NG\n"));
 //#endif
                        status = status_tmp & ~(FDC_ST_BUSY | FDC_ST_DRQ);
                        cmdtype = 0;
+                       set_drq(false);
                        set_irq(true);
                } else if(status_tmp & FDC_ST_WRITEFAULT) {
 //#ifdef _FDC_DEBUG_LOG
@@ -814,6 +871,7 @@ void MB8877::event_callback(int event_id, int err)
 //#endif
                        status = status_tmp & ~(FDC_ST_BUSY | FDC_ST_DRQ);
                        cmdtype = 0;
+                       set_drq(false);
                        set_irq(true);
                } else {
                        status = status_tmp | (FDC_ST_BUSY | FDC_ST_DRQ);
@@ -828,6 +886,7 @@ void MB8877::event_callback(int event_id, int err)
                        fdc[drvreg].prev_clock = prev_drq_clock = get_current_clock();
                        set_drq(true);
                        drive_sel = false;
+                       this->out_debug_log("DRQ ON@SEARCH: %d\n", prev_drq_clock);
 //#ifdef _FDC_DEBUG_LOG
                        if(fdc_debug_log) this->out_debug_log(_T("FDC\tSEARCH OK\n"));
 //#endif
@@ -846,10 +905,12 @@ void MB8877::event_callback(int event_id, int err)
                           cmdtype == FDC_CMD_WR_SEC || cmdtype == FDC_CMD_WR_MSEC ||
                           cmdtype == FDC_CMD_RD_TRK || cmdtype == FDC_CMD_WR_TRK  ||
                           cmdtype == FDC_CMD_RD_ADDR) {
-                               fdc[drvreg].index++;
+                               if(!(fdc[drvreg].count_immediate)) fdc[drvreg].index++;
                        }
                        fdc[drvreg].prev_clock = prev_drq_clock = get_current_clock();
+
                        set_drq(true);
+                       this->out_debug_log("DRQ ON@DRQ: %d\n", prev_drq_clock);
 //#ifdef _FDC_DEBUG_LOG
                        //this->out_debug_log(_T("FDC\tDRQ!\n"));
 //#endif
@@ -868,19 +929,34 @@ void MB8877::event_callback(int event_id, int err)
        case EVENT_LOST:
                if(status & FDC_ST_BUSY) {
 //#ifdef _FDC_DEBUG_LOG
-                               if(fdc_debug_log) this->out_debug_log(_T("FDC\tDATA LOST\n"));
+                       if(fdc_debug_log) this->out_debug_log(_T("FDC\tDATA LOST\n"));
 //#endif
                        if(cmdtype == FDC_CMD_WR_SEC || cmdtype == FDC_CMD_WR_MSEC || cmdtype == FDC_CMD_WR_TRK) {
-                               if(fdc[drvreg].index == 0) {
-                                       status &= ~FDC_ST_BUSY;
-                                       //status &= ~FDC_ST_DRQ;
+                               if(fdc[drvreg].index == 0) { // HEAD of REGION
                                        cmdtype = 0;
+                                       //if((status & FDC_ST_DRQ) != 0) { // 20180130 FORCE DOWN DRQ ON LOST-DATA.
+                                               status |= FDC_ST_LOSTDATA;
+                                               status &= (uint8_t)(~(FDC_ST_DRQ | FDC_ST_BUSY));
+                                               set_drq(false);
+                                               //}
                                        set_irq(true);
-                                       //set_drq(false);
-                               } else {
+                               } else { // STILL WRITING
                                        write_io8(3, 0x00);
+                                       //if((status & FDC_ST_DRQ) != 0) {
+                                               status |= FDC_ST_LOSTDATA;
+                                               status &= (uint8_t)(~(FDC_ST_DRQ | FDC_ST_BUSY));
+                                               set_irq(true);
+                                               set_drq(false);
+                                               //cmdtype = 0;
+                                               //}
                                }
-                       } else {
+                       } else { // READ 
+                               //if((status & FDC_ST_DRQ) != 0) {
+                                       status |= FDC_ST_LOSTDATA;
+                                       status &= (uint8_t)(~(FDC_ST_DRQ | FDC_ST_BUSY));
+                                       set_irq(true);
+                                       set_drq(false);
+                                       //}
                                read_io8(3);
                        }
                        status |= FDC_ST_LOSTDATA;
@@ -1047,8 +1123,26 @@ void MB8877::cmd_restore()
 {
        // type-1 restore
        cmdtype = FDC_CMD_TYPE1;
-       status = FDC_ST_HEADENG | FDC_ST_BUSY;
-       trkreg = 0xff;
+       if(!check_drive()) {
+               return;
+       }
+       if((cmdreg & 0x08) != 0) { // Head engage
+               status = FDC_ST_HEADENG | FDC_ST_BUSY;
+       } else {
+               status = FDC_ST_BUSY;
+       }
+       set_irq(false);
+       set_drq(false);
+
+       if(fdc[drvreg].track < 0) {
+               fdc[drvreg].track = 0;
+               trkreg = 0;
+       } else if(fdc[drvreg].track >= 80) {
+               fdc[drvreg].track = 80;
+               trkreg = 80;
+       } else {
+               trkreg = fdc[drvreg].track;
+       }
        datareg = 0;
        
        seektrk = 0;
@@ -1061,7 +1155,14 @@ void MB8877::cmd_seek()
 {
        // type-1 seek
        cmdtype = FDC_CMD_TYPE1;
-       status = FDC_ST_HEADENG | FDC_ST_BUSY;
+       if(!check_drive()) {
+               return;
+       }
+       if((cmdreg & 0x08) != 0) { // Head engage
+               status = FDC_ST_HEADENG | FDC_ST_BUSY;
+       } else {
+               status = FDC_ST_BUSY;
+       }               
        
 //     seektrk = (uint8_t)(fdc[drvreg].track + datareg - trkreg);
        seektrk = datareg;
@@ -1077,14 +1178,6 @@ void MB8877::cmd_seek()
        } else {
                seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
        }               
-//#else
-//     if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
-//#endif
-//             seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
-//     } else {
-//             seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
-//     }
-//     seekvct = !(datareg > trkreg);
        seekvct = !(seektrk > fdc[drvreg].track);
        
        if(cmdreg & 4) {
@@ -1111,18 +1204,15 @@ void MB8877::cmd_stepin()
 {
        // type-1 step in
        cmdtype = FDC_CMD_TYPE1;
-       status = FDC_ST_HEADENG | FDC_ST_BUSY;
-       
+       if(!check_drive()) {
+               return;
+       }
+       if((cmdreg & 0x08) != 0) { // Head engage
+               status = FDC_ST_HEADENG | FDC_ST_BUSY;
+       } else {
+               status = FDC_ST_BUSY;
+       }               
        seektrk = fdc[drvreg].track + 1;
-//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
-//     if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
-//#else
-//     if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
-//#endif
-//             seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
-//     } else {
-//             seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
-//     }
        if(type_fm77av_2dd) {
                if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
                        seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
@@ -1150,7 +1240,14 @@ void MB8877::cmd_stepout()
 {
        // type-1 step out
        cmdtype = FDC_CMD_TYPE1;
-       status = FDC_ST_HEADENG | FDC_ST_BUSY;
+       if(!check_drive()) {
+               return;
+       }
+       if((cmdreg & 0x08) != 0) { // Head engage
+               status = FDC_ST_HEADENG | FDC_ST_BUSY;
+       } else {
+               status = FDC_ST_BUSY;
+       }               
        
        seektrk = fdc[drvreg].track - 1;
        if(type_fm77av_2dd) {
@@ -1164,15 +1261,6 @@ void MB8877::cmd_stepout()
        } else {
                seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
        }               
-//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
-//     if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
-//#else
-//     if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
-//#endif
-//             seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
-//     } else {
-//             seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
-//     }
        seekvct = true;
        
        if(cmdreg & 4) {
@@ -1189,6 +1277,9 @@ void MB8877::cmd_readdata(bool first_sector)
 {
        // type-2 read data
        cmdtype = (cmdreg & 0x10) ? FDC_CMD_RD_MSEC : FDC_CMD_RD_SEC;
+       if(!check_drive2()) {
+               return;
+       }
        status = FDC_ST_BUSY;
        status_tmp = search_sector();
        now_search = true;
@@ -1207,6 +1298,9 @@ void MB8877::cmd_writedata(bool first_sector)
 {
        // type-2 write data
        cmdtype = (cmdreg & 0x10) ? FDC_CMD_WR_MSEC : FDC_CMD_WR_SEC;
+       if(!check_drive2()) {
+               return;
+       }
        status = FDC_ST_BUSY;
        status_tmp = search_sector() & ~FDC_ST_RECTYPE;
        now_search = true;
@@ -1228,6 +1322,9 @@ void MB8877::cmd_readaddr()
 {
        // type-3 read address
        cmdtype = FDC_CMD_RD_ADDR;
+       if(!check_drive2()) {
+               return;
+       }
        status = FDC_ST_BUSY;
        status_tmp = search_addr();
        now_search = true;
@@ -1246,6 +1343,9 @@ void MB8877::cmd_readtrack()
 {
        // type-3 read track
        cmdtype = FDC_CMD_RD_TRK;
+       if(!check_drive2()) {
+               return;
+       }
        status = FDC_ST_BUSY;
        status_tmp = 0;
        
@@ -1263,6 +1363,9 @@ void MB8877::cmd_writetrack()
 {
        // type-3 write track
        cmdtype = FDC_CMD_WR_TRK;
+       if(!check_drive2()) {
+               return;
+       }
        status = FDC_ST_BUSY;
        status_tmp = 0;
        
@@ -1357,7 +1460,7 @@ void MB8877::cmd_forceint()
 //#endif
                if(cmdtype == 0 || !(status & FDC_ST_BUSY)) {
                        cmdtype = FDC_CMD_TYPE1;
-                       status = FDC_ST_HEADENG;
+                   if(!type_fm7) status = FDC_ST_HEADENG; // Hack for FUKUALL.d77 .
                }
                status &= ~FDC_ST_BUSY;
                
@@ -1370,7 +1473,7 @@ void MB8877::cmd_forceint()
 //#endif
        
        cancel_my_event(EVENT_SEEK);
-       cancel_my_event(EVENT_SEEKEND);
+       cancel_my_event(EVENT_SEEKEND_VERIFY);
        cancel_my_event(EVENT_SEARCH);
        cancel_my_event(EVENT_DRQ);
        cancel_my_event(EVENT_MULTI1);
@@ -1406,6 +1509,13 @@ uint8_t MB8877::search_track()
                           (disk[drvreg]->drive_type == DRIVE_TYPE_144)) {
                                track >>= 1;
                        }
+               } else {        // OS-9 2DD Access fix by Ryu Takegami
+                       if((disk[drvreg]->media_type != MEDIA_TYPE_2D) &&
+                          (disk[drvreg]->media_type != MEDIA_TYPE_UNK)) {
+                               if(disk[drvreg]->drive_type == DRIVE_TYPE_2D) {
+                                       track <<= 1;
+                               }
+                       }
                }
        }
 //#endif
@@ -1461,6 +1571,13 @@ uint8_t MB8877::search_sector()
                           (disk[drvreg]->drive_type == DRIVE_TYPE_144)) {
                                track >>= 1;
                        }
+               } else {        // OS-9 2DD Access fix by Ryu Takegami
+                       if((disk[drvreg]->media_type != MEDIA_TYPE_2D) &&
+                          (disk[drvreg]->media_type != MEDIA_TYPE_UNK)) {
+                               if(disk[drvreg]->drive_type == DRIVE_TYPE_2D) {
+                                       track <<= 1;
+                               }
+                       }
                }
        }
 //#endif
@@ -1550,6 +1667,13 @@ uint8_t MB8877::search_addr()
                           (disk[drvreg]->drive_type == DRIVE_TYPE_144)) {
                                track >>= 1;
                        }
+               } else {        // OS-9 2DD Access fix by Ryu Takegami
+                       if((disk[drvreg]->media_type != MEDIA_TYPE_2D) &&
+                          (disk[drvreg]->media_type != MEDIA_TYPE_UNK)) {
+                               if(disk[drvreg]->drive_type == DRIVE_TYPE_2D) {
+                                       track <<= 1;
+                               }
+                       }
                }
        }
 //#endif
@@ -1695,6 +1819,15 @@ void MB8877::open_disk(int drv, const _TCHAR* file_path, int bank)
 {
        if(drv < _max_drive) {
                disk[drv]->open(file_path, bank);
+#if defined(_USE_QT)
+               if((disk[drv]->is_special_disk == SPECIAL_DISK_FM7_FLEX) || (config.disk_count_immediate[drv])) {
+#else
+               if(disk[drv]->is_special_disk == SPECIAL_DISK_FM7_FLEX) {
+#endif
+                       fdc[drv].count_immediate = true;
+               } else {
+                       fdc[drv].count_immediate = false;
+               }
        }
 }
 
@@ -1704,6 +1837,7 @@ void MB8877::close_disk(int drv)
                disk[drv]->close();
                cmdtype = 0;
                update_head_flag(drvreg, false);
+               fdc[drv].count_immediate = false;
        }
 }
 
@@ -1791,7 +1925,7 @@ void MB8877::update_config()
        }
 }
 
-#define STATE_VERSION  5
+#define STATE_VERSION  6
 
 void MB8877::save_state(FILEIO* state_fio)
 {